var allWorkItemTypes = [];
var selectedWorkItemTypesFilter = [];
var selectedWorkItemStatesFilter = [];
var selectedWorkItems = [];
var selectedWorkItemsObj = [];
var editMode = false;
var editEvolveId = "";
var organizationId = "";
var organizationName = "";
var projectName = "";
var generatedWorkItemIds = []; // Should always be int array
var devOpsProjectId = "";
var createdDate = "";
var modifiedDate = "";
var createdBy = "";
var modifiedBy = "";
var scopeLevelGlobal = 0;
var optimalRolloutSettings = "";
var azureAuthenticationHeader = "";
var pageSize = 50;
var currentWorkItemsPage;
let sortAsc = false;
var sortCol;
var taskListMode = "list";
var workItemsSuggestionsTimer;
var baseAPIUrl = "";
var publisherId = "";
var extensionId = "";
var userguidelink = "";
var userhelplink = "";
var existingSuggestions = "";
var acceptedSuggestions = "";
var suggestionsHistory = [];
var allowedSuggestionWorkItemTypes = []; // From backend configuration
var selectedSuggestionWorkItemTypes = []; // User's filtered selection
var workItemTypesParam = "";
var workItemStatesParam = "";
var acceptedsuggestions = "";
const RELATED_PAGE_SIZE = 6;
const GROUP_ORDER = [
    "Parent",
    "Child",
    "Predecessor",
    "Successor",
    "Related",
    "Duplicate",
    "Duplicate Of",
    "Tests",
    "Tested By",
    "Other"
];
let workItemStateColorMap = {};
var licensedUserType = "";
const fieldName = "eaUserType";
var requiredFieldDefaultsByWit = window.requiredFieldDefaultsByWit || {};
var requiredFieldDefaultsLoaded = window.requiredFieldDefaultsLoaded || false;
window.requiredFieldDefaultsByWit = requiredFieldDefaultsByWit;
window.requiredFieldDefaultsLoaded = requiredFieldDefaultsLoaded;

// --- Global state for Related Work panel ---
window._relatedWorkAll = window._relatedWorkAll || [];
window._relatedWorkExpanded = window._relatedWorkExpanded || false;
function eaEscapeHtml(value) {
    return String(value ?? "")
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#39;");
}

function eaSafeUrl(url) {
    const value = String(url ?? "").trim();
    return /^(https?:|data:image\/)/i.test(value) ? eaEscapeHtml(value) : "";
}

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

function updateKebabDropdownState() {
    const isProjectSaved = editEvolveId && editEvolveId !== "" && editEvolveId !== null && editEvolveId !== undefined;
    const renameBtn = document.querySelector('.header-kebab .rename-project');
    const deleteBtn = document.querySelector('.header-kebab .delete-project');

    if (renameBtn) {
        renameBtn.disabled = !isProjectSaved;
        renameBtn.style.opacity = isProjectSaved ? '1' : '0.5';
        renameBtn.style.cursor = isProjectSaved ? 'pointer' : 'not-allowed';
    }

    if (deleteBtn) {
        deleteBtn.disabled = !isProjectSaved;
        deleteBtn.style.opacity = isProjectSaved ? '1' : '0.5';
        deleteBtn.style.cursor = isProjectSaved ? 'pointer' : 'not-allowed';
    }
}

async function OpenRenameModal() {
    if (!editEvolveId || !projectName) {
        Swal.fire("Error", "No project selected!", "error");
        return;
    }
    // Get current user and organization details
    const modifiedBy = IndexLibrary.GetUserEmail();
    const organizationId = IndexLibrary.GetAccountId();

    const { value: newName } = await Swal.fire({
        title: "Rename Project",
        input: "text",
        inputLabel: "Project Name",
        inputValue: projectName,
        showCancelButton: true,
        confirmButtonText: "Save",
        cancelButtonText: "Cancel",
        inputValidator: (value) => {
            if (!value.trim()) return "Project name cannot be empty!";
            const regex = /^[a-zA-Z0-9 _-]+$/;
            if (!regex.test(value.trim()))
                return "Project name can only contain letters, numbers, spaces, hyphens, and underscores!";
            return null;
        },
    });

    if (newName && newName.trim() !== "") {
        try {
            const response = await IndexLibrary.PutRequest({
                endpoint: "/api/EvolveAssist/UpdateName",
                body: {
                    id: editEvolveId,
                    organizationId: organizationId,
                    projectName: newName.trim(),
                    modifiedBy: modifiedBy,
                },
            });

            if (response.ok) {
                projectName = newName.trim();
                $("#heading").text(projectName);
                await Swal.fire("Success", "Project name updated successfully!", "success");
            } else {
                const errorText = await response.text();
                Swal.fire("Error", "Failed to rename project: " + errorText, "error");
            }
        } catch (error) {
            Swal.fire("Error", "An error occurred: " + error.message, "error");
        }
    }
}

async function DeleteEvolveAssistProject() {
    if (!editEvolveId) {
        return;
    }

    const deletedBy = IndexLibrary.GetUserEmail();
    const organizationId = IndexLibrary.GetAccountId();

    const confirmResult = await Swal.fire({
        title: "Delete Chat",
        text: `Are you sure you want to delete "${projectName}"? This action cannot be undone.`,
        icon: "warning",
        showCancelButton: true,
        confirmButtonText: "Delete",
        cancelButtonText: "Cancel",
        confirmButtonColor: "#d33",
    });

    if (confirmResult.isConfirmed) {
        try {
            const response = await IndexLibrary.DeleteRequest({
                endpoint: "/api/EvolveAssist/DeleteEvolveAssistProject",
                body: {
                    projectId: editEvolveId,
                    organizationId: organizationId,
                    deletedBy: deletedBy,
                },
            });

            if (response.ok) {
                await Swal.fire("Deleted!", "Project has been deleted successfully.", "success");
                // Navigate back to the list
                await NavigateToAssistList();
            } else {
                const errorText = await response.text();
                Swal.fire("Error", "Failed to delete project: " + errorText, "error");
            }
        } catch (error) {
            Swal.fire("Error", "An error occurred: " + error.message, "error");
        }
    }
}

async function waitForWorkItemTypes() {
    return new Promise(resolve => {
        const checkLoaded = () => {
            if (allWorkItemTypes && allWorkItemTypes.length > 0) {
                resolve();
            } else {
                setTimeout(checkLoaded, 50);
            }
        };
        checkLoaded();
    });
}


document.addEventListener("DOMContentLoaded", async () => {
    // Attach toggle behavior to all menu components
    document.querySelectorAll(".menu-component").forEach(component => {
        const button = component.querySelector(".menu-button");
        button.addEventListener("click", (e) => {
            e.stopPropagation();
            component.classList.toggle("active");
        });
    });

    // Close menus when clicking outside
    document.addEventListener("click", () => {
        document.querySelectorAll(".menu-component.active")
            .forEach(c => c.classList.remove("active"));
    });
    await waitForWorkItemTypes(); // ensures icons are loaded
    const params = new URLSearchParams(window.location.search);
    const idParam = params.get("workItemId");
    if (!selectedWorkItemForFilter && idParam) {
        const workItemId = parseInt(idParam);
        await loadWorkItemIntoFilter(workItemId);
    }

    await applyCreateWorkItemsPermission();
});

// -------------------------
// HELPER TO RENDER LIST
// -------------------------
function renderList(listEl, items) {
    const html = items.map(item => {
        const title = item.title || item.Title || "";
        const desc = item.description || item.Description || "";
        const category = item.category || item.Category || item.type || item.Type || "Task";

        const iconUrl =
            allWorkItemTypes.find(x => x.name === category)?.iconUrl ||
            allWorkItemTypes[0]?.iconUrl;

        return `
        <li class="list-group-item bg-gray"
            data-category="${eaEscapeHtml(category)}"
            data-item='${eaEscapeHtml(JSON.stringify(item))}'
        >
          <img src="${eaSafeUrl(iconUrl)}" alt="${eaEscapeHtml(category)}" />
          <div style="flex: 1;">
            <strong>${eaEscapeHtml(title)}</strong>
            ${desc ? `<div style="font-size: 12px; color: #666; margin-top: 2px;">${eaSanitizeRichText(desc)}</div>` : ""}
          </div>
        </li>`;
    }).join("");

    listEl.innerHTML = html;
}

function renderList(listEl, items) {
    const html = items.map(item => {
        const title = item.title || item.Title || "";
        const desc = item.description || item.Description || "";
        const category = item.category || item.Category || item.type || item.Type || "Task";

        const iconUrl =
            allWorkItemTypes.find(x => x.name === category)?.iconUrl ||
            allWorkItemTypes[0]?.iconUrl;

        return `
        <li class="list-group-item bg-gray"
            data-category="${eaEscapeHtml(category)}"
            data-item='${eaEscapeHtml(JSON.stringify(item))}'
        >
          <img src="${eaSafeUrl(iconUrl)}" alt="${eaEscapeHtml(category)}" />
          <div style="flex: 1;">
            <strong>${eaEscapeHtml(title)}</strong>
            ${desc ? `<div style="font-size: 12px; color: #666; margin-top: 2px;">${eaSanitizeRichText(desc)}</div>` : ""}
          </div>
        </li>`;
    }).join("");

    listEl.innerHTML = html;
}
async function loadWorkItemIntoFilter(workItemId) {
    try {
        const result = await IndexLibrary.getWorkItemsByIds([workItemId]);

        if (!result || result.length === 0) return;

        const wi = result[0];

        selectedWorkItemForFilter = {
            id: String(wi.id),
            title: wi.title,
            type: wi.type,
            project: wi.project,
            state: wi.state,
            description: wi.description || "",
            acceptanceCriteria: wi.acceptanceCriteria || ""
        };

        updateFilterDisplay();
        refreshRelatedOrGeneratedPanel();
    } catch (err) {
        console.error("Failed to load work item into filter:", err);
    }
}

function refreshRelatedOrGeneratedPanel() {
    updateRelatedPanelHeader();

    if (selectedWorkItemForFilter && selectedWorkItemForFilter.id) {
        showRelatedWorkItems(selectedWorkItemForFilter.id);
        return;
    }

    if (generatedWorkItemIds && generatedWorkItemIds.length > 0) {
        loadGeneratedWorkItemsFromIds();
    } else {
        const container = document.getElementById("list-related");
        container.innerHTML = `
            <li class="list-group-item text-center text-muted small">
                No generated work items
            </li>`;
    }
}


$(document).on('click', '.rename-project', function (event) {
    if (!$(this).data('eaid')) {
        if ($(this).is(':disabled') || $(this).prop('disabled')) {
            event.preventDefault();
            event.stopPropagation();
            return false;
        }
        event.preventDefault();
        event.stopPropagation();
        OpenRenameModal();
        $(this).closest('.dropdown').removeClass('show');
        $(this).closest('.dropdown-menu').removeClass('show');
        return false;
    }
});

$(document).on('click', '.delete-project', async function (event) {
    if (!$(this).data('eaid')) {
        if ($(this).is(':disabled') || $(this).prop('disabled')) {
            event.preventDefault();
            event.stopPropagation();
            return false;
        }
        event.preventDefault();
        event.stopPropagation();
        $(this).closest('.dropdown').removeClass('show');
        $(this).closest('.dropdown-menu').removeClass('show');
        await DeleteEvolveAssistProject();
        return false;
    }
});



function RemoveWorkItem(workItemId, rowId) {
    var itemIndex = selectedWorkItems.indexOf(parseInt(workItemId));
    selectedWorkItems.splice(itemIndex, 1);
    var row = document.getElementById(rowId);
    row.parentNode.removeChild(row);
}

IndexLibrary.InitializeSDK().then(async function () {
    organizationName = await IndexLibrary.GetAccountNameAsync();
    organizationId = await IndexLibrary.GetAccountIdAfterInit();
    azureAuthenticationHeader = await IndexLibrary.GetAccessToken();
    const config = await IndexLibrary.GetExtensionConfig();
    baseAPIUrl = config.apiBaseUrl;
    publisherId = config.publisherId;
    extensionId = config.extensionId;
    userguidelink = config.userguidelink;
    userhelplink = config.userhelplink;
    IndexLibrary.GetRequest({
        endpoint:
            `/api/License/IsUserLicensed?organizationName=${organizationName}&email=${IndexLibrary.GetUserEmail()}&moduleUserType=devOpsAssist`,
    })
        .then((response) => response.text())
        .then(function (data) {
            if (data.toLowerCase() == "false") {
                $("#main").hide();
                $("#licenseExpired").hide();
                $("#unauthorized").show();
            } else {
                IndexLibrary.GetRequest({
                    endpoint: `/api/License/IsOrgLicenseValid?organizationName=${organizationName}`,
                })
                    .then((orgLicenseValidityResponse) =>
                        orgLicenseValidityResponse.text()
                    )
                    .then(function (orgLicenseValidityData) {
                        if (orgLicenseValidityData.toLowerCase() == "false") {
                            $("#main").hide();
                            $("#unauthorized").hide();
                            $("#licenseExpired").show();
                            $("#loadingSpinner").hide();
                        } else {
                            $("#main").show();
                            $("#unauthorized").hide();
                            $("#licenseExpired").hide();
                            IndexLibrary.GetRequest({
                                endpoint: "/api/Settings/Get",
                            })
                                .then((response) => response.json())
                                .then(async function (data) {
                                    optimalRolloutSettings = data;
                                    pageSize = optimalRolloutSettings.pageSizeForTables;
                                    updateScopeText(data.projectScope);

                                    const devOpsProjectIdValue = (devOpsProjectId && devOpsProjectId !== "")
                                        ? devOpsProjectId
                                        : await IndexLibrary.GetCurrentProjectId();
                                    IndexLibrary.GetRequest({
                                        endpoint: `/api/AzureDevOps/GetWorkItemTypesByProject?projectId=${devOpsProjectIdValue}`,
                                    })
                                        .then((response) => response.json())
                                        .then(async function (workItemTypesResponse) {
                                            allWorkItemTypes = workItemTypesResponse;
                                            workItemStateColorMap = buildStateColorMap(allWorkItemTypes);

                                            await loadRequiredFieldDefaultsForCurrentProject();

                                            $("#taskSuggestions").hide();

                                            // Initialize suggestion type filter first, then populate dropdowns
                                            loadAllowedSuggestionTypes();

                                            if (
                                                editEvolveId !== null &&
                                                editEvolveId !== undefined
                                            ) {
                                                editMode = true;
                                                ShowEditMode();
                                            } else {
                                                $("#loadingSpinner").hide();
                                            }
                                        });
                                });
                        }
                    });
            }
        });
});

function openUserGuideLink() {
    IndexLibrary.openInNewTab(userguidelink);
}

function openUserHelpLink() {
    IndexLibrary.openInNewTab(userhelplink);
}

function applySavedFilters(savedTypes, savedStates) {

    // Check type checkboxes
    savedTypes.forEach(type => {
        $(`.chkWorkItemFilter[data-work-item-type="${type}"]`)
            .prop("checked", true)
            .trigger("change");
    });
    // Check state checkboxes
    savedStates.forEach(state => {
        $(`.chkWorkItemStateFilter[data-work-item-state="${state}"]`)
            .prop("checked", true)
            .trigger("change");
    });
}

$(document).ready(async function () {

    const urlParams = new URLSearchParams(window.location.search);
    editEvolveId = urlParams.get("eId");
    updateKebabDropdownState();
    $("#taskSuggestions").hide();
    $("#unauthorized").hide();
    $("#licenseExpired").hide();

    $(document).on("click", function (e) {
        if (
            !e.target.classList.contains("suggestion") &&
            !e.target.closest(".work-item-suggestion") &&
            e.target.id !== "txtFilter"
        ) {
            $("#taskSuggestions").hide();
        }
    });

    makeSelectable("list-suggestions");
    makeSelectable("list-accepted");

    // Initialize tooltips for collapsed panels
    initializeTooltips();

    const listSuggestions = document.getElementById("list-suggestions");
    const listAccepted = document.getElementById("list-accepted");

    document
        .getElementById("move-selected-right")
        .addEventListener("click", () => {
            moveSelected(listSuggestions, listAccepted);
            moveSelectedHistoryItems(listAccepted);
            savePanelState();
        });

    $(document).on("click", "#createWorkItemsCustomSettings", function (e) {
        e.preventDefault();
        handleCreateWorkItemsClick(true);
    });

    document.getElementById("move-all-right").addEventListener("click", () => {
        moveAll(listSuggestions, listAccepted);
        savePanelState();
    });

    document
        .getElementById("move-selected-left")
        .addEventListener("click", () => {
            moveSelected(listAccepted, listSuggestions);
            savePanelState();
        });

    document.getElementById("move-all-left").addEventListener("click", () => {
        moveAll(listAccepted, listSuggestions);
        savePanelState();
    });

    //Microphone functionality
    const SpeechRecognition =
        window.SpeechRecognition || window.webkitSpeechRecognition;
    const recognition = new SpeechRecognition();
    recognition.interimResults = true; // get partial results as you speak
    //  recognition.lang = 'en-US';        // set language

    recognition.addEventListener("result", (e) => {
        const transcript = Array.from(e.results)
            .map((result) => result[0].transcript)
            .join("");
        document.getElementById("suggestion_input").value = transcript;
    });
});

//Microphone functionality
function speak() {
    navigator.mediaDevices
        .getUserMedia({ audio: true })
        .then((stream) => {
            console.log("Microphone access granted");
            recognition.start();
            document.getElementById("mic_button_start").classList.add("d-none");
            document.getElementById("mic_button_stop").classList.remove("d-none");
        })
        .catch((err) => {
            console.error("Error accessing microphone:", err);
            IndexLibrary.ShowToast('error',
                "Microphone access is required to use this feature. Please enable microphone permissions in your browser settings."
            );
        });
}

function stop() {
    recognition.stop();
    document.getElementById("mic_button_stop").classList.add("d-none");
    document.getElementById("mic_button_start").classList.remove("d-none");
}

// Update URL using modern Azure DevOps Extension SDK
// This calls the function exposed from index.ts
function safeUpdateUrl(projectId) {
    if (typeof window.updateEvolveAssistUrl === 'function') {
        window.updateEvolveAssistUrl(projectId);
    } else {
        // Retry after a short delay to allow SDK to initialize
        setTimeout(() => {
            if (typeof window.updateEvolveAssistUrl === 'function') {
                window.updateEvolveAssistUrl(projectId);
            }
        }, 500);
    }
}

function getSuggestionCategory(item) {
    return item?.category || item?.Category || item?.type || item?.Type || "Task";
}

function getSuggestionTitleValue(item) {
    return item?.title || item?.Title || "";
}

function getSelectableSuggestionTypes() {
    return allWorkItemTypes
        .filter((type) => allowedSuggestionWorkItemTypes.includes(type.name))
        .map((type) => type.name);
}

function getEffectiveSelectedTypes() {
    return selectedSuggestionWorkItemTypes.length
        ? selectedSuggestionWorkItemTypes
        : getSelectableSuggestionTypes();
}

function areAllSuggestionTypesConsidered() {
    if (!selectedSuggestionWorkItemTypes.length) return true;

    const selectableTypes = getSelectableSuggestionTypes();
    if (!selectableTypes.length) return true;

    return selectableTypes.every((name) =>
        selectedSuggestionWorkItemTypes.includes(name)
    );
}

function parseSuggestionsArray(raw) {
    if (!raw) return [];
    if (Array.isArray(raw)) return raw;
    try {
        const parsed = JSON.parse(raw);
        return Array.isArray(parsed) ? parsed : [];
    } catch {
        return [];
    }
}

function collectPreviouslyGeneratedSuggestions() {
    const flatHistory = (suggestionsHistory || []).reduce(
        (acc, batch) => acc.concat(Array.isArray(batch) ? batch : []),
        []
    );

    const combined = [
        ...parseSuggestionsArray(existingSuggestions),
        ...parseSuggestionsArray(acceptedSuggestions),
        ...flatHistory,
    ];

    const seen = new Set();
    const deduped = [];
    combined.forEach((s) => {
        const key = `${getSuggestionTitleValue(s)}|${getSuggestionCategory(s)}`
            .trim()
            .toLowerCase();
        if (seen.has(key)) return;
        seen.add(key);
        deduped.push(s);
    });
    return deduped;
}

function buildExclusionSuggestions() {
    const all = collectPreviouslyGeneratedSuggestions();

    let result;
    if (areAllSuggestionTypesConsidered()) {
        result = all;
    } else {
        const selectedSet = new Set(
            selectedSuggestionWorkItemTypes.map((t) => normalizeKey(t))
        );
        result = all.filter((s) =>
            selectedSet.has(normalizeKey(getSuggestionCategory(s)))
        );
    }

    return result.length ? JSON.stringify(result) : null;
}

async function fetchAISuggestions(promptText, onComplete = null) {
    var projectId = (editEvolveId == null || editEvolveId == undefined || editEvolveId == "") ? 0 : parseInt(editEvolveId, 10);
    const suggestionsUrl = `${baseAPIUrl}/api/EvolveAssist/GetSuggestions`;
    const listEl = document.getElementById("list-suggestions");
    if (!listEl) return;

    // Build related work items array from window._relatedWorkAll
    let relatedWorkItems = [];
    if (window._relatedWorkAll && window._relatedWorkAll.length > 0) {
        relatedWorkItems = window._relatedWorkAll.map(item => ({
            id: String(item.id),
            title: item.title,
            state: item.state,
            type: item.type,
            linkType: item.linkType,
            description: item.description || "",
            acceptanceCriteria: item.acceptanceCriteria || ""
        }));
    }

    // Prepare request body
    // Ensure proper GUID handling - get from IndexLibrary if global variables are empty
    const devOpsProjectIdValue = (devOpsProjectId && devOpsProjectId !== "")
        ? devOpsProjectId
        : await IndexLibrary.GetCurrentProjectId();

    const organizationIdValue = (organizationId && organizationId !== "")
        ? organizationId
        : IndexLibrary.GetAccountId();

    const devOpsProjectNameValue = (projectName && projectName !== "")
        ? projectName
        : await IndexLibrary.GetCurrentProjectName();

    const requestBody = {
        ProjectId: projectId,
        OrganizationId: organizationIdValue,
        DevOpsProjectId: devOpsProjectIdValue || null,
        DevOpsProjectName: devOpsProjectNameValue,
        CreatedBy: createdBy || IndexLibrary.GetUserEmail(),
        Suggestions: promptText,
        ConversationHistory: [],
        WorkItemContext: (selectedWorkItemForFilter && selectedWorkItemForFilter.id)
            ? {
                ...selectedWorkItemForFilter,
                relatedWorkItems: relatedWorkItems
            }
            : null,
        ExistingSuggestions: buildExclusionSuggestions(),
        AcceptedSuggestions: acceptedSuggestions || null,
        SelectedSuggestionWorkItemTypes: getEffectiveSelectedTypes().length > 0
            ? getEffectiveSelectedTypes()
            : null
    };

    IndexLibrary.PostRequest({
        endpoint: "/api/EvolveAssist/GetSuggestions",
        body: requestBody
    })
        .then((res) => {
            if (!res.ok) {
                // Get error text from this response (don't make another request)
                return res.text().then((errorText) => {
                    throw { status: res.status, errorText: errorText };
                });
            }
            return res.json();
        })
        .then((data) => {
            // Check if AI needs more context
            if (data.needsMoreContext === true) {
                // Store projectId but DON'T update URL yet (to prevent page reload and popup disappearing)
                // URL will be updated after chat completes and suggestions are generated
                if (data.projectId) {
                    editEvolveId = data.projectId;
                    updateKebabDropdownState();
                }

                // Open chat dialog with the AI's question
                openChatDialog(promptText, data.message);

                if (onComplete) {
                    onComplete();
                }
                return;
            }

            // AI has provided suggestions - display them
            const suggestions = data?.suggestions?.Suggestions || [];

            if (!suggestions.length) {
                listEl.innerHTML =
                    "<li class='list-group-item bg-gray'>No suggestions returned</li>";
                return;
            }

            // Update editEvolveId and URL in all scenarios
            if (data.projectId) {
                editEvolveId = data.projectId;
                safeUpdateUrl(editEvolveId);
                updateKebabDropdownState();
            }

            // Generate HTML for suggestions
            const html = suggestions
                .map((item) => {
                    // Handle both lowercase and Title case properties
                    const title = item.title || item.Title || "";
                    const desc = item.description || item.Description || "";
                    const category = item.category || item.Category || item.type || item.Type || "Task";

                    // Find appropriate icon
                    const iconUrl =
                        allWorkItemTypes.find((x) => x.name === category)?.iconUrl ||
                        allWorkItemTypes[0]?.iconUrl;

                    return `
        <li class="list-group-item bg-gray" data-category="${eaEscapeHtml(category)}"
            data-item='${eaEscapeHtml(JSON.stringify(item))}'
        >
              <img src="${eaSafeUrl(iconUrl)}" alt="${eaEscapeHtml(category)}" />
              <div style="flex: 1;">
                <strong>${eaEscapeHtml(title)}</strong>
                ${desc
                            ? `<div style="font-size: 12px; color: #666; margin-top: 2px;">${eaSanitizeRichText(desc)}</div>`
                            : ""
                        }
              </div>
            </li>
          `;
                })
                .join("");

            listEl.innerHTML = html;

            // Await saveChatSuggestions to ensure backend processes suggestions before loading
            saveChatSuggestions({ projectId: data.projectId, queryContext: promptText, suggestions: data.suggestions.Suggestions }).then(() => {
                // Load project data after saving to get the latest suggestions and history
                if (editEvolveId) {
                    loadProjectData(editEvolveId).then(() => {
                        if (onComplete) {
                            onComplete();
                        }
                    });
                } else {
                    if (onComplete) {
                        onComplete();
                    }
                }
            });
        })
        .catch((err) => {
            console.error("Error fetching suggestions:", err);

            // Show detailed error
            const listEl = document.getElementById("list-suggestions");
            if (listEl) {
                let errorMessage = "";

                if (err.message && err.message.includes("Failed to fetch")) {
                    errorMessage = "Network error - please check:<br>" +
                        "1. API server is running at " + suggestionsUrl + "<br>" +
                        "2. SSL certificate is trusted (ERR_CERT_AUTHORITY_INVALID)<br>" +
                        "3. CORS is configured correctly";
                } else if (err.status === 400 && err.errorText) {
                    // Business logic errors from the API
                    errorMessage = err.errorText;

                    // Special handling for duplicate project name
                    if (err.errorText.includes("active project with this name already exists")) {
                        errorMessage = "?? " + err.errorText + "<br><br>" +
                            "?? <strong>Tip:</strong> Try a different query or delete the existing project first.";
                    }
                } else if (err.errorText) {
                    errorMessage = err.errorText;
                } else {
                    errorMessage = err.message || "Unknown error occurred";
                }

                listEl.innerHTML =
                    `<li class='list-group-item bg-gray' style='white-space: pre-wrap;'>${eaEscapeHtml(errorMessage)}</li>`;
            }

            if (onComplete) {
                onComplete();
            }
        });
}

function parseMarkdownWorkItems(text) {
    const workItems = [];

    const match = text.match("Work Items");
    if (!match) return workItems;

    const startIndex = match.index + match[0].length;
    const workItemsSection = text.slice(startIndex);

    const itemBlocks = workItemsSection.split(/####\s+\*\*Title:\*\*/);

    for (let i = 1; i < itemBlocks.length; i++) {
        const block = itemBlocks[i].trim();
        const lines = block.split(/\r?\n/);
        const title = lines[0]?.trim() || "";

        let description = "";
        let category = "";

        for (const line of lines) {
            if (line.startsWith("**Description:**")) {
                description = line.replace("**Description:**", "").trim();
            } else if (line.startsWith("**Category:**")) {
                category = line.replace("**Category:**", "").trim();
            }
        }

        if (title && description && category) {
            workItems.push({ title, description, category });
        }
    }

    return workItems;
}

function createSuggestion() {
    const suggestionText = document
        .getElementById("suggestion_input")
        .value.trim();

    if (!suggestionText) {
        Swal.fire({
            title: "No Input",
            text: "Please enter some text in the suggestion box before creating a suggestion.",
            icon: "warning",
            confirmButtonColor: "#0078d4",
        });
        return;
    }

    // Show loading state
    const generateBtn = document.getElementById("generate_suggestions_btn");
    const originalText = generateBtn.textContent;
    generateBtn.disabled = true;
    generateBtn.innerHTML =
        '<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>Generating...';

    // Directly fetch AI suggestions without token count popup
    try {
        fetchAISuggestions(suggestionText, (res) => {
            generateBtn.disabled = false;
            generateBtn.innerHTML = originalText;
        });
    } catch (error) {
        generateBtn.disabled = false;
        generateBtn.innerHTML = originalText;

        Swal.fire({
            title: "Error!",
            text: "Failed to generate suggestions. Please try again later.",
            icon: "error",
            confirmButtonColor: "#d33",
        });
    }
}

// Toggle selection (active) on click
function makeSelectable(listId) {
    const element = document.getElementById(listId);
    if (!element) {
        console.warn(`makeSelectable: Element with id '${listId}' not found`);
        return;
    }
    element.addEventListener("click", function (e) {
        const item = e.target.closest(".list-group-item");
        if (!item) return;
        item.classList.toggle("active");
    });
}

function moveSelected(from, to) {
    const items = Array.from(from.querySelectorAll(".list-group-item.active"));
    items.forEach((li) => {
        li.classList.remove("active");
        to.appendChild(li);
    });

    // Update tooltips for both panels if they are collapsed
    const fromPanel = from.closest(".col-md-3");
    const toPanel = to.closest(".col-md-3");

    if (fromPanel.classList.contains("panel-collapsed")) {
        const panelType = from.id.includes("suggestions")
            ? "suggestions"
            : "accepted";
        addTooltipsToPanel(panelType);
    }

    if (toPanel.classList.contains("panel-collapsed")) {
        const panelType = to.id.includes("suggestions")
            ? "suggestions"
            : "accepted";
        addTooltipsToPanel(panelType);
    }

    updateCreateWorkItemsButtonState();
}

function moveSelectedHistoryItems(to) {
    // Get selected history items (those with "active" class)
    const historyItems = $("#suggestions-history-list .list-group-item.active");

    historyItems.each(function () {
        // Remove active class and history-specific click handlers
        $(this).removeClass("active").off("click");
        $(to).append(this);
    });

    // Update the suggestionsHistory array to reflect current DOM state
    const updatedHistory = [];
    $("#suggestions-history-list > div").each(function () {
        const items = [];
        $(this).find(".list-group-item").each(function () {
            try {
                const itemData = JSON.parse($(this).attr("data-item"));
                items.push(itemData);
            } catch (e) {
                console.error("Error parsing history item:", e);
            }
        });

        // Only add non-empty sets
        if (items.length > 0) {
            updatedHistory.push(items);
        }
    });

    // Update global suggestionsHistory array
    suggestionsHistory = updatedHistory;

    // Re-render history if no items left in a set (clean up empty divs)
    $("#suggestions-history-list > div").each(function () {
        if ($(this).find(".list-group-item").length === 0) {
            $(this).remove();
        }
    });

    // Hide history container if no history items left
    if (suggestionsHistory.length === 0) {
        $("#suggestions-history-container").hide();
    } else {
        // Update count
        $("#history-count").text(suggestionsHistory.length);
    }

    updateCreateWorkItemsButtonState();
}

function moveAll(from, to) {
    const items = Array.from(from.querySelectorAll(".list-group-item"));
    items.forEach((li) => {
        li.classList.remove("active");
        to.appendChild(li);
    });

    // Update tooltips for both panels if they are collapsed
    const fromPanel = from.closest(".col-md-3");
    const toPanel = to.closest(".col-md-3");

    if (fromPanel.classList.contains("panel-collapsed")) {
        const panelType = from.id.includes("suggestions")
            ? "suggestions"
            : "accepted";
        addTooltipsToPanel(panelType);
    }

    if (toPanel.classList.contains("panel-collapsed")) {
        const panelType = to.id.includes("suggestions")
            ? "suggestions"
            : "accepted";
        addTooltipsToPanel(panelType);
    }

    updateCreateWorkItemsButtonState();
}

function updateCreateWorkItemsButtonState() {
    const btn = document.getElementById("btnCreateWorkItems");
    const dropdownBtn = document.getElementById("btnCreateWorkItemsDropdown");
    const wrapper = document.getElementById("createWorkItemsWrapper");
    if (!btn || !wrapper) return;

    if (licensedUserType === "0") {
        btn.disabled = true;
        if (dropdownBtn) dropdownBtn.disabled = true;
        wrapper.title = "Only Manager can create work item";
        return;
    }
    wrapper.title = "";

    const acceptedList = document.getElementById("list-accepted");
    const acceptedItems = acceptedList?.querySelectorAll(".list-group-item") || [];
    const shouldDisable = acceptedItems.length === 0;

    btn.disabled = shouldDisable;
    if (dropdownBtn) dropdownBtn.disabled = shouldDisable;
}

/**
 * Cleans up raw ADO API errors for user display.
 * @param {Error} err - The error object from a catch block.
 * @returns {string} - A cleaner, more user-friendly error message.
 */
function formatErrorMessage(err) {
    let msg = err.message || "An unknown error occurred.";

    // Remove common technical prefixes
    if (msg.includes("TFS.WebApi.Exception:")) {
        msg = msg.split("TFS.WebApi.Exception:")[1]?.trim();
    }
    if (msg.includes("VS402323:")) {
        msg = msg.split("VS402323:")[1]?.trim();
    }
    if (msg.includes("TFS.WebApi.Exception:") || msg.includes("VS402323:")) {
        msg = "The API returned an error. Please check the work item type and project permissions.";
    }

    return msg;
}

function updateRelatedPanelHeader() {
    const header = document.getElementById("related-header");
    const abbrev = document.getElementById("rg-abbrev");
    if (!header) return;

    if (selectedWorkItemForFilter == null) {
        abbrev.setAttribute("data-abbrev", "G");
        header.innerText = "Generated Work Items";
    } else {
        abbrev.setAttribute("data-abbrev", "R");
        header.innerText = "Related Work Items";
    }
}


async function handleCreateWorkItemsClick(forceCustomSettings = false) {
    const btn = document.getElementById("btnCreateWorkItems");
    const acceptedList = document.getElementById("list-accepted");
    const acceptedItems = Array.from(
        acceptedList.querySelectorAll(".list-group-item")
    );

    const totalItems = acceptedItems.length;
    if (totalItems === 0) {
        Swal.fire("No Items", "Please accept at least one suggestion.", "warning");
        return;
    }

    btn.disabled = true;
    const originalText = btn.innerText;
    const failedItems = [];
    const successfulIds = [];

    const parentId = window.selectedWorkItemForFilter?.id || null;

    const suggestions = acceptedItems.map((item) => ({
        element: item,
        title: item.querySelector("strong")?.innerText?.trim() || "Untitled",
        description: item.querySelector("div > div")?.innerText?.trim() || "",
        category: item.dataset.category || "Task",
    }));

    let chatId = editEvolveId && editEvolveId !== "" ? parseInt(editEvolveId, 10) : null;

    const defaultsByWit = await loadRequiredFieldDefaultsForCurrentProject();
    const chatDefaultsByWit = await fetchDefaultFieldsByChatId(chatId);
    const effectiveDefaultsByWit = mergeDefaultsByWit(defaultsByWit, chatDefaultsByWit);
    const witNames = [...new Set(suggestions.map((item) => String(item.category || '').trim()).filter(Boolean))];
    const requiredFieldsByWit = await fetchConfigurableFieldsByWitFromProjectDb(
        (devOpsProjectId && devOpsProjectId !== '')
            ? devOpsProjectId
            : await IndexLibrary.GetCurrentProjectId(),
        witNames,
        chatId
    );

    let effectiveRequiredFieldsByWit = requiredFieldsByWit;
    if (Object.keys(requiredFieldsByWit).length === 0) {
        effectiveRequiredFieldsByWit = createBasicRequiredFields(witNames);
    }

    const missingByWit = forceCustomSettings
        ? getAllRequiredFieldsByWit(effectiveRequiredFieldsByWit)
        : getMissingRequiredFieldsByWit(effectiveRequiredFieldsByWit, effectiveDefaultsByWit);

    let userProvidedByWit = {};
    if (Object.keys(missingByWit).length > 0) {
        const witGroupsForPopup = await prepareRequiredFieldGroupsForPopup(missingByWit, forceCustomSettings ? effectiveDefaultsByWit : {});

        if (Object.keys(witGroupsForPopup).length > 0) {
            userProvidedByWit = await showRequiredFieldsPopupForMultipleWITs(witGroupsForPopup, allWorkItemTypes, false);

            if (userProvidedByWit === null) {
                btn.innerText = originalText;
                btn.disabled = false;
                updateCreateWorkItemsButtonState();
                return;
            }
        }

        if (Object.keys(userProvidedByWit).length > 0) {
            try {
                await saveCustomDefaultsForChat(userProvidedByWit, requiredFieldsByWit, chatId, effectiveDefaultsByWit);
            } catch (saveError) {
                Swal.fire('Warning', 'Work item creation will continue, but custom settings could not be saved for this chat. Error: ' + saveError.message, 'warning');
            }
        }
    }

    for (let i = 0; i < totalItems; i++) {
        const suggestionItem = suggestions[i];
        const item = suggestionItem.element;
        const title = suggestionItem.title;

        btn.innerText = `Creating ${i + 1} of ${totalItems}...`;

        const suggestion = {
            title: suggestionItem.title,
            description: suggestionItem.description,
            category: suggestionItem.category,
        };

        try {
            const createdId = await createWorkItemWithRequiredFields(
                suggestion,
                parentId,
                effectiveDefaultsByWit,
                userProvidedByWit,
                requiredFieldsByWit
            );
            successfulIds.push(createdId);
            item.remove();

        } catch (err) {
            console.error(`Failed to create work item "${title}":`, err);
            const friendlyError = formatErrorMessage(err);
            failedItems.push({ title: title, error: friendlyError });
        }
    }

    let beSaveError = null;
    if (successfulIds.length > 0) {
        btn.innerText = "Saving created items...";

        try {
            const appendRequest = {
                ProjectId: editEvolveId,
                OrganizationId: organizationId,
                DevOpsProjectId: devOpsProjectId || await IndexLibrary.GetCurrentProjectId(),
                ModifiedBy: IndexLibrary.GetUserEmail(),
                NewWorkItemIds: successfulIds,
            };

            let response = await IndexLibrary.PostRequest({
                baseAPIUrl: baseAPIUrl,
                endpoint: "/api/EvolveAssist/AppendWorkItems",
                azureAuthenticationHeader: azureAuthenticationHeader,
                organizationName: await IndexLibrary.GetAccountNameAsync(),
                organizationId: organizationId,
                body: appendRequest
            });

            // Backward-compatible fallback in case backend only accepts PATCH.
            if (!response.ok && (response.status === 404 || response.status === 405)) {
                response = await IndexLibrary.PatchRequest({
                    baseAPIUrl: baseAPIUrl,
                    endpoint: "/api/EvolveAssist/AppendWorkItems",
                    azureAuthenticationHeader: azureAuthenticationHeader,
                    organizationName: await IndexLibrary.GetAccountNameAsync(),
                    organizationId: organizationId,
                    body: appendRequest,
                });
            }

            if (!response.ok) {
                throw new Error(`Server responded with ${response.status}. Failed to save work item IDs.`);
            }

            const allClientIds = new Set(generatedWorkItemIds.map(id => parseInt(id, 10)));
            successfulIds.forEach(id => allClientIds.add(id).add(parseInt(id, 10)));
            generatedWorkItemIds = Array.from(allClientIds);

        } catch (err) {
            console.error("Failed to save work item IDs to BE:", err);
            beSaveError = err.message;
        }
    }

    const dropdownBtn = document.getElementById("btnCreateWorkItemsDropdown");
    btn.disabled = false;
    if (dropdownBtn) { dropdownBtn.disabled = false; dropdownBtn.style.opacity = "1"; }
    btn.innerText = originalText;
    updateCreateWorkItemsButtonState();
    // document.getElementById("list-suggestions").innerHTML = "";

    refreshRelatedOrGeneratedPanel();

    const successCount = successfulIds.length;
    const failureCount = failedItems.length;
    if (failureCount === 0) { //&& !beSaveError
        Swal.fire(
            "Success!",
            `Successfully created and saved all ${successCount} work item(s).`,
            "success"
        );
        clearAcceptedList();
    } else if (successCount === 0 && failureCount > 0) {
        Swal.fire({
            title: "All Items Failed",
            icon: "error",
            html: `
        <p>Could not create any of the ${totalItems} work item(s). Please review the errors below:</p>
        <ul style="text-align: left; list-style-position: inside; max-height: 200px; overflow-y: auto;">
          ${failedItems.map(f => `
            <li>
              <strong>${f.title}</strong><br>
              <small style="color: #6c757d;">${f.error}</small>
            </li>`).join("")}
        </ul>
      `,
        });
    } else {
        let errorHtml = "";
        if (failureCount > 0) {
            errorHtml += `
        <p><strong>Failed to create ${failureCount} item(s):</strong></p>
        <ul style="text-align: left; list-style-position: inside; max-height: 150px; overflow-y: auto;">
          ${failedItems.map(f => `
            <li>
              <strong>${f.title}</strong><br>
              <small style="color: #6c757d;">${f.error}</small>
            </li>`).join("")}
        </ul>`;
        }

        if (beSaveError) {
            errorHtml += `
        <hr>
        <p class.danger-text">
          <strong>Important:</strong> ${successCount} item(s) were created in ADO,
          but <strong>failed to save</strong> to the project.
          <br><small style="color: #6c757d;">Error: ${beSaveError}</small>
        </p>`;
        }

        Swal.fire({
            title: beSaveError ? "Partial Success with Save Error" : "Partial Success",
            icon: "warning",
            html: `
        <p>Successfully created <strong>${successCount}</strong> out of <strong>${totalItems}</strong> work item(s).</p>
        ${errorHtml}
      `,
        });
    }
}




/**
 * Creates a SINGLE work item in Azure DevOps.
 * @param {object} suggestion - The suggestion object { title, description, category }.
 * @param {string|null} parentId - The ID of the parent work item, if any.
 * @returns {Promise<number>} - The ID of the newly created work item.
 */
async function createWorkItemsInAzureDevOps(suggestion, parentId = null) {
    return new Promise(async (resolve, reject) => {
        try {
            const project = await IndexLibrary.GetCurrentProjectName();
            const accountName = organizationName || await IndexLibrary.GetAccountNameAsync();

            // This function will create the one item
            const createOne = async (sugg) => {
                const workItemPatch = [
                    { op: "add", path: "/fields/System.Title", value: sugg.title },
                    {
                        op: "add",
                        path: "/fields/System.Description",
                        value: sugg.description || "",
                    },
                ];

                // Add parent link if parentId is provided
                if (parentId) {
                    workItemPatch.push({
                        op: "add",
                        path: "/relations/-",
                        value: {
                            rel: "System.LinkTypes.Hierarchy-Reverse",
                            url: `https://dev.azure.com/${accountName}/_apis/wit/workItems/${parentId}`,
                        },
                    });
                }

                // Create the item using the dynamic category, defaulting to "Task"
                const workItemType = sugg.category || "Task";
                // const wi = await witClient.createWorkItem(
                //     workItemPatch,
                //     project,
                //     workItemType
                // );
                const wi = await IndexLibrary.CreateWorkItemsInDevops(
                    workItemPatch,
                    project,
                    workItemType
                );

                // Resolve the promise with the single new ID
                resolve(wi.id);
            };

            // --- THIS IS THE FIX ---
            // Execute the creation and add a .catch(reject)
            // This ensures any API error (like a 404) is correctly
            // passed to the outer promise's reject function.
            createOne(suggestion).catch(reject);
            // --- END OF FIX ---

        } catch (e) {
            // This catches synchronous errors (e.g., VSS.require fails)
            reject(e);
        }

    });
}

const EA_NON_FORM_FIELDS = new Set([
    'System.Id', 'System.AreaId', 'System.IterationId', 'System.Rev',
    'System.AuthorizedDate', 'System.RevisedDate', 'System.Watermark',
    'System.TeamProject', 'System.PersonId', 'System.AttachedFileCount',
    'System.ExternalLinkCount', 'System.HyperLinkCount', 'System.CommentCount',
    'System.AuthorizedAs', 'System.BoardColumn', 'System.BoardColumnDone',
    'System.BoardLane', 'System.ChangedDate', 'System.NodeName',
    'System.Title', 'System.State'
]);

function hasUsableDefaultValue(value) {
    if (value === null || value === undefined) return false;
    if (typeof value === 'string') return value.trim() !== '';
    return true;
}

function getFieldValueCaseInsensitive(obj, key) {
    if (!obj || typeof obj !== 'object') return undefined;
    const matchedKey = Object.keys(obj).find(k => k.toLowerCase() === key.toLowerCase());
    return matchedKey ? obj[matchedKey] : undefined;
}

function normalizeKey(value) {
    return String(value || '').trim().toLowerCase();
}

function getByNormalizedKey(sourceObj, rawKey) {
    if (!sourceObj || typeof sourceObj !== 'object') return undefined;
    const normalizedTarget = normalizeKey(rawKey);
    const matchedKey = Object.keys(sourceObj).find((key) => normalizeKey(key) === normalizedTarget);
    return matchedKey ? sourceObj[matchedKey] : undefined;
}

function isValueWithinAllowedValues(allowedValues, value) {
    if (!Array.isArray(allowedValues) || allowedValues.length === 0) return true;
    if (!hasUsableDefaultValue(value)) return true;
    const target = normalizeKey(value);
    return allowedValues.some((allowed) => normalizeKey(allowed) === target);
}

function parseDefaultFieldsFromResponse(data) {
    if (!Array.isArray(data)) return {};

    const defaultsByWit = {};
    data.forEach((field) => {
        const workItemTypeName = getFieldValueCaseInsensitive(field, 'workItemTypeName');
        const fieldReferenceName = getFieldValueCaseInsensitive(field, 'fieldReferenceName');
        const defaultValue = getFieldValueCaseInsensitive(field, 'defaultValue');

        if (!workItemTypeName || !fieldReferenceName || !hasUsableDefaultValue(defaultValue)) {
            return;
        }

        if (!defaultsByWit[workItemTypeName]) {
            defaultsByWit[workItemTypeName] = {};
        }

        defaultsByWit[workItemTypeName][fieldReferenceName] = defaultValue;
    });

    return defaultsByWit;
}
async function resolveProcessIdFromProject(projectId) {
    if (!projectId) return null;
    try {
        const orgName = await IndexLibrary.GetAccountNameAsync();

        const projectRes = await IndexLibrary.GetRequest({
            baseAPIUrl: `https://dev.azure.com/${orgName}`,
            endpoint: `/_apis/projects/${encodeURIComponent(projectId)}?includeCapabilities=true&api-version=7.0`,
            headers: {
                'Authorization': `Bearer ${azureAuthenticationHeader}`,
                'Content-Type': 'application/json'
            }
        });

        if (projectRes.ok) {
            const projectData = await projectRes.json();
            if (projectData.capabilities && projectData.capabilities.processTemplate && projectData.capabilities.processTemplate.templateTypeId) {
                return projectData.capabilities.processTemplate.templateTypeId;
            }
        }

        const res = await IndexLibrary.GetRequest({
            baseAPIUrl: `https://dev.azure.com/${orgName}`,
            endpoint: `/_apis/projects/${encodeURIComponent(projectId)}/properties?api-version=7.1-preview.1`,
            headers: {
                'Authorization': `Bearer ${azureAuthenticationHeader}`,
                'Content-Type': 'application/json'
            }
        });
        if (!res.ok) return null;
        const data = await res.json();
        const prop = (data.value || []).find(p => p.name === 'System.ProcessTemplateType');
        return prop ? prop.value : null;
    } catch (e) {
        console.error('Error resolving process ID:', e);
        return null;
    }
}

async function fetchDefaultFieldsByWorkItemType(projectId) {
    if (!projectId || !organizationId) {
        return {};
    }

    try {
        const processId = await resolveProcessIdFromProject(projectId);
        if (!processId) {
            return {};
        }

        const response = await IndexLibrary.GetRequest({
            endpoint: `/api/Settings/GetWorkItemDefaultFieldsByProcess/${organizationId}/${processId}`,
        });

        if (!response.ok) {
            return {};
        }

        const data = await response.json();
        return parseDefaultFieldsFromResponse(data);
    } catch (e) {
        return {};
    }
}

async function fetchDefaultFieldsByChatId(chatId) {
    if (!chatId || chatId <= 0) {
        return {};
    }

    try {
        const response = await IndexLibrary.GetRequest({
            endpoint: `/api/Settings/GetWorkItemDefaultFieldsByChat/${organizationId}/${chatId}`,
        });

        if (!response.ok) {
            return {};
        }

        const data = await response.json();
        return parseDefaultFieldsFromResponse(data);
    } catch (e) {
        return {};
    }
}

async function loadRequiredFieldDefaultsForCurrentProject(forceRefresh = false) {
    // Defensive initialization for scenarios where script reload/caching causes state vars to be missing.
    if (typeof requiredFieldDefaultsByWit === 'undefined') {
        requiredFieldDefaultsByWit = window.requiredFieldDefaultsByWit || {};
    }
    if (typeof requiredFieldDefaultsLoaded === 'undefined') {
        requiredFieldDefaultsLoaded = window.requiredFieldDefaultsLoaded || false;
    }

    if (requiredFieldDefaultsLoaded && !forceRefresh) {
        if (Object.keys(requiredFieldDefaultsByWit || {}).length === 0) {
            return loadRequiredFieldDefaultsForCurrentProject(true);
        }
        return requiredFieldDefaultsByWit;
    }

    try {
        const currentProjectId = (devOpsProjectId && devOpsProjectId !== '')
            ? devOpsProjectId
            : await IndexLibrary.GetCurrentProjectId();

        requiredFieldDefaultsByWit = await fetchDefaultFieldsByWorkItemType(currentProjectId);
        requiredFieldDefaultsLoaded = Object.keys(requiredFieldDefaultsByWit || {}).length > 0;
        window.requiredFieldDefaultsByWit = requiredFieldDefaultsByWit;
        window.requiredFieldDefaultsLoaded = requiredFieldDefaultsLoaded;
        return requiredFieldDefaultsByWit;
    } catch (e) {
        console.error('Error loading required field defaults from DB:', e);
        requiredFieldDefaultsByWit = {};
        requiredFieldDefaultsLoaded = false;
        window.requiredFieldDefaultsByWit = requiredFieldDefaultsByWit;
        window.requiredFieldDefaultsLoaded = requiredFieldDefaultsLoaded;
        return {};
    }
}

function createBasicRequiredFields(witNames) {
    return (witNames || []).reduce((acc, name) => {
        if (name) acc[name] = [];
        return acc;
    }, {});
}

function getAllRequiredFieldsByWit(requiredFieldsByWit) {
    const allRequiredByWit = {};

    Object.keys(requiredFieldsByWit || {}).forEach((witName) => {
        const requiredFields = requiredFieldsByWit[witName] || [];
        const filteredFields = requiredFields.filter((field) => {
            if (!field || !field.referenceName) return false;
            return !EA_NON_FORM_FIELDS.has(field.referenceName);
        });

        if (filteredFields.length > 0) {
            allRequiredByWit[witName] = filteredFields;
        }
    });

    return allRequiredByWit;
}

function getMissingRequiredFieldsByWit(requiredFieldsByWit, defaultsByWit) {
    const missingByWit = {};

    Object.keys(requiredFieldsByWit || {}).forEach((witName) => {
        const requiredFields = requiredFieldsByWit[witName] || [];
        const defaults = getByNormalizedKey(defaultsByWit, witName) || {};

        const missingFields = requiredFields.filter((field) => {
            if (!field || !field.referenceName) return false;
            if (EA_NON_FORM_FIELDS.has(field.referenceName)) return false;
            const value = getByNormalizedKey(defaults, field.referenceName);
            return value === undefined || value === null || String(value).trim() === '';
        });

        if (missingFields.length > 0) {
            missingByWit[witName] = missingFields;
        }
    });

    return missingByWit;
}

function mergeDefaultsByWit(projectDefaultsByWit, chatDefaultsByWit) {
    const merged = {};

    Object.keys(projectDefaultsByWit || {}).forEach((witName) => {
        merged[witName] = {
            ...(projectDefaultsByWit[witName] || {})
        };
    });

    Object.keys(chatDefaultsByWit || {}).forEach((witName) => {
        if (!merged[witName]) {
            merged[witName] = {};
        }

        merged[witName] = {
            ...merged[witName],
            ...(chatDefaultsByWit[witName] || {})
        };
    });

    return merged;
}

async function getProcessName(processId) {
    try {
        const orgName = await IndexLibrary.GetAccountNameAsync();
        const response = await IndexLibrary.GetRequest({
            baseAPIUrl: `https://dev.azure.com/${orgName}`,
            endpoint: `/_apis/process/processes/${processId}?api-version=7.1-preview.1`,
            headers: {
                'Authorization': `Bearer ${azureAuthenticationHeader}`,
                'Content-Type': 'application/json'
            }
        });
        if (response.ok) {
            const data = await response.json();
            return data.name || 'Process';
        }
    } catch (e) {
    }
    return 'Process';
}

async function saveCustomDefaultsForChat(userProvidedByWit, requiredFieldsByWit, chatId, effectiveDefaultsByWit = {}) {
    if (!userProvidedByWit || Object.keys(userProvidedByWit).length === 0) {
        return;
    }

    if (!chatId || chatId <= 0) {
        return;
    }

    const currentProjectId = (devOpsProjectId && devOpsProjectId !== '')
        ? devOpsProjectId
        : await IndexLibrary.GetCurrentProjectId();
    const currentProjectName = (projectName && projectName !== '')
        ? projectName
        : await IndexLibrary.GetCurrentProjectName();

    const processId = await resolveProcessIdFromProject(currentProjectId);
    if (!processId) {
        throw new Error('Could not resolve process ID for project');
    }

    const processName = await getProcessName(processId);
    const orgNameForHeaders = organizationName || await IndexLibrary.GetAccountNameAsync();

    const saveCalls = [];

    Object.keys(userProvidedByWit || {}).forEach((witName) => {
        const fieldValues = userProvidedByWit[witName] || {};
        const requiredFields = getByNormalizedKey(requiredFieldsByWit, witName) || [];
        const existingDefaults = getByNormalizedKey(effectiveDefaultsByWit, witName) || {};

        Object.keys(fieldValues).forEach((fieldRef) => {
            const newValue = fieldValues[fieldRef];
            const existingValue = getByNormalizedKey(existingDefaults, fieldRef);

            if (existingValue === newValue) {
                return;
            }

            const fieldMeta = requiredFields.find((field) => normalizeKey(field.referenceName) === normalizeKey(fieldRef)) || {};
            const payload = {
                OrganizationId: organizationId,
                DevOpsProcessId: processId,
                DevOpsProcessName: processName,
                WorkItemTypeName: witName,
                FieldReferenceName: fieldRef,
                FieldName: fieldMeta.name || fieldRef,
                FieldType: fieldMeta.type || 'string',
                DefaultValue: newValue,
                CreatedBy: IndexLibrary.GetUserEmail()
            };

            if (chatId && chatId > 0) {
                payload.ChatId = chatId;
            }

            const apiCall = IndexLibrary.PostRequest({
                endpoint: '/api/Settings/UpsertWorkItemDefaultField',
                organizationId: organizationId,
                organizationName: orgNameForHeaders,
                azureAuthenticationHeader: azureAuthenticationHeader,
                body: payload
            }).then(async (response) => {
                if (!response.ok) {
                    throw new Error(`API call failed with status ${response.status}`);
                }
                return response;
            });

            saveCalls.push(apiCall);
        });
    });

    if (saveCalls.length === 0) {
        return;
    }

    const responses = await Promise.all(saveCalls);
    const failedCount = responses.filter((response) => !response.ok).length;
    if (failedCount > 0) {
        throw new Error(`Failed to save ${failedCount} custom field value(s).`);
    }
}

/**
 * @param {object} suggestion - The suggestion object { title, description, category }
 * @param {string|null} parentId - The ID of the parent work item, if any
 * @returns {Promise<number>} - The ID of the newly created work item
 */
async function createWorkItemWithRequiredFields(
    suggestion,
    parentId = null,
    defaultsByWit = {},
    userProvidedByWit = {},
    requiredFieldsByWit = {}
) {
    try {
        const accountName = organizationName || await IndexLibrary.GetAccountNameAsync();
        const project = await IndexLibrary.GetCurrentProjectName();
        const workItemType = suggestion.category || "Task";
        const workItemPatch = [
            { op: "add", path: "/fields/System.Title", value: suggestion.title },
            {
                op: "add",
                path: "/fields/System.Description",
                value: suggestion.description || "",
            },
        ];

        const dbDefaults = getByNormalizedKey(defaultsByWit, workItemType) || {};
        const userValues = getByNormalizedKey(userProvidedByWit, workItemType) || {};
        const requiredFields = getByNormalizedKey(requiredFieldsByWit, workItemType) || [];

        requiredFields.forEach((fieldMeta) => {
            if (!fieldMeta || !fieldMeta.referenceName || EA_NON_FORM_FIELDS.has(fieldMeta.referenceName)) {
                return;
            }

            const fieldRef = fieldMeta.referenceName;
            const userValue = getByNormalizedKey(userValues, fieldRef);
            const dbValue = getByNormalizedKey(dbDefaults, fieldRef);
            let selectedValue = null;

            if (hasUsableDefaultValue(userValue)) {
                selectedValue = userValue;
            } else if (hasUsableDefaultValue(dbValue)) {
                selectedValue = dbValue;
            }

            if (!hasUsableDefaultValue(selectedValue)) {
                return;
            }

            if (!isValueWithinAllowedValues(fieldMeta.allowedValues, selectedValue)) {
                return;
            }

            const exists = workItemPatch.some((patchOp) => patchOp.path === `/fields/${fieldRef}`);
            if (exists) {
                return;
            }

            workItemPatch.push({
                op: "add",
                path: `/fields/${fieldRef}`,
                value: selectedValue
            });
        });

        if (parentId) {
            workItemPatch.push({
                op: "add",
                path: "/relations/-",
                value: {
                    rel: "System.LinkTypes.Hierarchy-Reverse",
                    url: `https://dev.azure.com/${accountName}/_apis/wit/workItems/${parentId}`,
                },
            });
        }

        const wi = await IndexLibrary.CreateWorkItemsInDevops(
            workItemPatch,
            project,
            workItemType
        );

        return wi.id;
    } catch (e) {
        console.error('Error creating work item with required fields:', e);
        throw e;
    }
}


function WorkItemFilterKeyUp() {
    if ($("#txtFilter").val() == "") {
        workItemsSuggestionsTimer = window.setTimeout(getRecentWorkItem, 100);
    } else {
        workItemsSuggestionsTimer = window.setTimeout(GetWorkItemSuggestions, 100);
    }
}

function WorkItemFilterKeyDown() {
    window.clearTimeout(workItemsSuggestionsTimer);
}

$(".chkWorkItemStateFilter").on("click", function () {
    if ($(this).is(":checked")) {
        selectedWorkItemStatesFilter.push($(this).data("workItemState"));
    } else {
        var itemIndex = selectedWorkItemStatesFilter.indexOf(
            $(this).data("workItemState")
        );
        if (itemIndex > -1) {
            selectedWorkItemStatesFilter.splice(itemIndex, 1);
        }
    }

    if (selectedWorkItemStatesFilter.length == 0) {
        $("#dropdownWorkItemStatusFilter").text("Task Status");
        $("#dropdownWorkItemStatusFilter").css("font-weight", "normal");
        $("#dropdownWorkItemStatusFilter").css("color", "#757575");
    } else {
        $("#dropdownWorkItemStatusFilter").text(
            selectedWorkItemStatesFilter[0] +
            (selectedWorkItemStatesFilter.length > 1
                ? "(+" + (selectedWorkItemStatesFilter.length - 1).toString() + ")"
                : "")
        );
        $("#dropdownWorkItemStatusFilter").css("font-weight", "bold");
        $("#dropdownWorkItemStatusFilter").css("color", "black");
    }
});




function renderWorkItemRow(item, devOpsProjectName) {
    const workItemUrl = `https://dev.azure.com/${organizationName}/${devOpsProjectName}/_workitems/edit/${item.id}`;
    const iconUrl = allWorkItemTypes.find(x => x.name === item.type)?.iconUrl || "";
    const typeKey = item.type ? item.type.trim().toLowerCase() : "";
    const stateKey = item.state ? item.state.trim().toLowerCase() : "";

    let rawColor = workItemStateColorMap?.[typeKey]?.[stateKey]?.color;

    if (typeof rawColor === "string" && /^[0-9a-f]{6}$/i.test(rawColor)) {
        rawColor = `#${rawColor}`;
    }

    // Validate color
    const isLikelyColor = c =>
        typeof c === "string" && (/^#/i.test(c) || /^rgb\(/i.test(c));

    // Final state color (ADO-defined, safe fallback)
    const stateColor = isLikelyColor(rawColor)
        ? rawColor
        : "rgb(178, 178, 178)";


    const hasAssignedTo =
        item.assignedTo &&
        item.assignedTo.trim &&
        item.assignedTo.trim() !== "";

    const userInitials = hasAssignedTo
        ? (item.assignedTo.split(" ").length >= 2
            ? (
                item.assignedTo.split(" ")[0][0] +
                item.assignedTo.split(" ")[1][0]
            ).toUpperCase()
            : item.assignedTo.substring(0, 2).toUpperCase())
        : "";

    const cleanState = item.state ? item.state.trim() : "";

    return `
        <li class="list-group-item" style="padding: 0; overflow: hidden;">
            <div class="removable-item-container full-width" style="display: flex; width: 100%; min-width: 0;">
                <div class="artifact-link-container artifact-link padding-bottom-8"
                    style="flex: 1; padding: 8px; min-width: 0; overflow: hidden;">
        
                    <div class="flex-row flex-center artifact-link"
                        style="display: flex; align-items: center; flex-wrap: nowrap; min-width: 0;">
        
                        <img src="${eaSafeUrl(iconUrl)}" alt="${eaEscapeHtml(item.type)}"
                            style="width: 16px; height: 16px; margin-right: 8px; flex-shrink: 0;" />
        
                        ${hasAssignedTo ? `
                        <div style="margin-right: 8px; flex-shrink: 0;">
                            <div class="bolt-coin avatar-circle" aria-label="${eaEscapeHtml(item.assignedTo)}">
                                ${eaEscapeHtml(userInitials)}
                            </div>
                        </div>
                        ` : ""}
        
                        <div class="artifact-link-id secondary-text margin-right-4"
                            style="margin-right: 4px; color: #666; font-size: 14px; flex-shrink: 0;">
                            ${eaEscapeHtml(item.id)}
                        </div>
        
                        <a class="artifact-link-link bolt-link no-underline-link related-work-title"
                        href="${eaSafeUrl(workItemUrl)}"
                        target="_blank"
                        rel="noopener noreferrer"
                        tabindex="0"
                        title="${eaEscapeHtml(item.title)}"
                        style="color: #0078d4; text-decoration: none; overflow: hidden;
                                text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0;">
                            ${eaEscapeHtml(item.title)}
                        </a>
                    </div>
        
                    <div class="artifact-details margin-left-16 flex-row flex-center"
                        style="margin-left: 16px; display: flex; align-items: center; margin-top: 4px;">
        
                        <span class="padding-right-8 text-ellipsis"
                            style="padding-right: 8px; color: #000; font-size: 12px;">
                            Updated <time class="bolt-time-item white-space-nowrap"
                                        style="white-space: nowrap;">${eaEscapeHtml(item.updated)}</time>
                        </span>
        
                    <span class="state-text"
                            style="--state-color:${eaEscapeHtml(stateColor)}">
                            ${eaEscapeHtml(cleanState)}
                        </span>
                    </div>
                </div>
            </div>
        </li>`;
}


async function loadGeneratedWorkItemsFromIds() {
    const container = document.getElementById("list-related");

    if (!generatedWorkItemIds || generatedWorkItemIds.length === 0) {
        container.innerHTML = `
            <li class="list-group-item text-center text-muted small">
                No generated work items
            </li>`;
        return;
    }

    try {
        const devOpsProjectName = await IndexLibrary.GetCurrentProjectName();
        organizationName = await IndexLibrary.GetAccountNameAsync();

        const validIds = generatedWorkItemIds
            .map(id => parseInt(id))
            .filter(id => !isNaN(id) && id > 0);

        if (validIds.length === 0) {
            container.innerHTML = `
                <li class="list-group-item text-center text-muted small">
                    No valid work item IDs found
                </li>`;
            return;
        }

        const items = await IndexLibrary.GetWorkItemsInDevops(
            validIds,
            devOpsProjectName,
            [
                "System.Id",
                "System.Title",
                "System.State",
                "System.WorkItemType",
                "System.ChangedDate",
                "System.TeamProject",
                "System.AssignedTo"
            ]
        );

        const normalizedItems = (items || [])
            .filter(wi => wi && wi.id) // Filter out null/undefined items
            .map(wi => ({
                id: wi.id,
                title: wi.fields["System.Title"] || "Untitled",
                state: wi.fields["System.State"] || "Unknown",
                type: wi.fields["System.WorkItemType"] || "Unknown",
                assignedTo: wi.fields["System.AssignedTo"]?.displayName || null,
                updated: wi.fields["System.ChangedDate"]
                    ? new Date(wi.fields["System.ChangedDate"]).toLocaleDateString("en-GB", {
                        day: "numeric",
                        month: "short"
                    })
                    : ""
            }));

        if (normalizedItems.length === 0) {
            container.innerHTML = `
                <li class="list-group-item text-center text-muted small">
                    No accessible work items found
                </li>`;
            return;
        }

        const html = normalizedItems
            .map(wi => renderWorkItemRow(wi, devOpsProjectName))
            .join("");

        container.innerHTML = html;

    } catch (err) {
        console.error("Failed to load generated work items:", err);
        container.innerHTML = `
            <li class="list-group-item text-center text-muted small">
                Failed to load generated work items
            </li>`;
    }
}


async function loadProjectData(projectId, skipHistoryRender = false) {

    try {
        const res = await IndexLibrary.GetRequest({
            endpoint: `/api/EvolveAssist/Get/${projectId}`,
        });
        if (res.status === 404) {
            await navigateToCreateProject();
            return null;
        }

        if (!res.ok) throw new Error(`Failed to load project ${projectId}`);

        const projectData = await res.json();

        organizationId = projectData.organizationId;
        projectName = projectData.projectName;
        $("#heading").text(projectName);

        createdDate = new Date(projectData.createdDate).toLocaleDateString("en-US");
        modifiedDate = new Date(projectData.modifiedDate).toLocaleDateString("en-US");

        updateKebabDropdownState();

        if (projectData.workItemIds) {
            generatedWorkItemIds = projectData.workItemIds
                ? projectData.workItemIds.split(",").map(id => parseInt(id, 10))
                : [];
        }
        devOpsProjectId = projectData.devOpsProjectId;
        createdBy = projectData.createdBy;
        modifiedBy = projectData.modifiedBy;

        refreshRelatedOrGeneratedPanel();
        existingSuggestions = projectData.suggestions || "";
        acceptedSuggestions = projectData.acceptedSuggestions || "";
        if (!skipHistoryRender) {
            if (projectData.suggestionsHistory) {
                try {
                    suggestionsHistory = JSON.parse(projectData.suggestionsHistory);
                    renderSuggestionsHistory();
                } catch (e) {
                    console.error("Error parsing suggestions history:", e);
                    suggestionsHistory = [];
                }
            } else {
                suggestionsHistory = [];
                $("#suggestions-history-container").hide();
            }
        }


        document.getElementById("suggestion_input").value = projectData.queryContext || "";

        const suggestions = projectData.suggestions ? JSON.parse(projectData.suggestions) : [];
        const accepted = projectData.acceptedSuggestions ? JSON.parse(projectData.acceptedSuggestions) : [];
        renderList(document.getElementById("list-suggestions"), suggestions);
        renderList(document.getElementById("list-accepted"), accepted);
        if (accepted.length > 0) {
            updateCreateWorkItemsButtonState();
        }

        // Filters
        const FilterTypes = projectData.filterTypes ? projectData.filterTypes.split(",") : [];
        const FilterStates = projectData.filterStates ? projectData.filterStates.split(",") : [];
        setTimeout(() => {
            applySavedFilters(FilterTypes, FilterStates);
        }, 200);

        if (projectData.linkedItem) {
            try {
                const item = JSON.parse(projectData.linkedItem);
                if (item.title && item.type) {
                    selectedWorkItemForFilter = item;
                    await loadWorkItemIntoFilter(item.id);
                } else {
                    selectedWorkItemForFilter = null;
                    document.getElementById("txtFilter").value = projectData.linkedItem;
                }
            } catch {
                selectedWorkItemForFilter = null;
                document.getElementById("txtFilter").value = projectData.linkedItem;
            }
        } else {
            selectedWorkItemForFilter = null;
        }

        updateFilterDisplay();
        updateRelatedPanelHeader();

        return projectData;

    } catch (error) {
        console.error("Error loading project data:", error);
        await Swal.fire({
            icon: "error",
            title: "Error",
            text: `Failed to load project: ${error.message}`,
            confirmButtonText: "OK"
        });
        return null;
    }
}

function ShowEditMode() {
    $("#btnCreateProject").show();
    $("#editModeControls").show();

    loadProjectData(editEvolveId).then(() => {
        $("#loadingSpinner").hide();
    });
}

async function GetWorkItemSuggestions() {

    let currentProject = scopeLevelGlobal === 1 ? await IndexLibrary.GetCurrentProjectName() : "";

    // Convert arrays to properly encoded comma-separated strings
    workItemTypesParam = selectedWorkItemTypesFilter.join(",");
    workItemStatesParam = selectedWorkItemStatesFilter.join(",");

    // Build URL
    var endpoint =
        `/api/AzureDevops/GetFilteredWorkItemsEvolveAssist?` +
        `filter=${encodeURIComponent($("#txtFilter").val())}` +
        `&workItemtypes=${encodeURIComponent(workItemTypesParam)}` +
        `&teamProject=${encodeURIComponent(currentProject)}` +
        `&workItemStates=${encodeURIComponent(workItemStatesParam)}`;

    IndexLibrary.GetRequest({ endpoint: endpoint })

        .then((response) => response.json())
        .then(function (items) {
            var suggestionsHtml = "";
            items = items || [];
            if (items.length === 0) {
                suggestionsHtml = "<span><i>No matching work items found</i></span>";
            } else {
                if (items.length > 0) {
                    suggestionsHtml =
                        "<div style='font-weight: 600; font-size:15px; height: 36px;  '> Work items </div>";
                }
                for (
                    var suggestedItemIndex = 0;
                    suggestedItemIndex < items.length;
                    suggestedItemIndex++
                ) {
                    var sDate = new Date(items[suggestedItemIndex].startDate);
                    var eDate = new Date(items[suggestedItemIndex].endDate);
                    var rowId =
                        items[suggestedItemIndex].id +
                        "_" +
                        items[suggestedItemIndex].project;
                    suggestionsHtml =
                        suggestionsHtml +
                        "<div class='work-item-suggestion' style='font-size:15px;height:30px;vertical-align:middle;cursor:pointer;padding:5px;border-radius:3px;' " +
                        "data-workitem-id='" +
                        items[suggestedItemIndex].id +
                        "' " +
                        "data-workitem-title='" +
                        items[suggestedItemIndex].title.replace(/'/g, "&#39;") +
                        "' " +
                        "data-workitem-type='" +
                        items[suggestedItemIndex].type +
                        "' " +
                        "data-workitem-project='" +
                        items[suggestedItemIndex].project +
                        "' " +
                        "data-workitem-state='" +
                        items[suggestedItemIndex].state +
                        "' " +
                        "onclick='addWorkItemToFilter(this)'>";
                    suggestionsHtml =
                        suggestionsHtml +
                        "<span class='search-suggestion-icon flex-row flex-noshrink'><img class='suggestion' src='" +
                        allWorkItemTypes.find(
                            (x) => x.name == items[suggestedItemIndex].type
                        ).iconUrl +
                        "' style='min-width: 14px;height: 14px;' /></span><span class='search-suggestion-title text-ellipsis' style='padding-left:8px'> " +
                        items[suggestedItemIndex].title +
                        "</span> <span style='color: var(--text-secondary-color, rgba(0, 0, 0, .55));padding-left:8px'> #" +
                        items[suggestedItemIndex].id;
                    suggestionsHtml = suggestionsHtml + "</span></div>";
                }
            }
            if (suggestionsHtml.trim() !== "") {
                $("#taskSuggestions").html(suggestionsHtml);
                $("#taskSuggestions").show();
            }

        });
}

async function getRecentWorkItem() {
    // Define the WIQL query to fetch recent work items
    var currentProjectName = await IndexLibrary.GetCurrentProjectName();

    var wiqlQuery;

    if (scopeLevelGlobal === 1) {
        // Only current project
        wiqlQuery = {
            query: `
        SELECT [System.Id], [System.Title], [System.State], [System.ChangedDate], [System.TeamProject]
        FROM WorkItems
        WHERE [System.TeamProject] = '${currentProjectName}'
        ORDER BY [System.ChangedDate] DESC
    `
        };
    } else {
        // All projects in the organization
        wiqlQuery = {
            query: `
        SELECT [System.Id], [System.Title], [System.State], [System.ChangedDate], [System.TeamProject]
        FROM WorkItems
        ORDER BY [System.ChangedDate] DESC
    `
        };
    }

    const queryResult = await IndexLibrary.ExecuteQueryByWiql(wiqlQuery);
    var suggestionsHtml = "";

    if (queryResult.workItems.length === 0) {

        $("#taskSuggestions").html(
            "<span><i>No recent work items found</i></span>"
        );
        $("#taskSuggestions").show();
    } else {
        var recentWorkItemIds = queryResult.workItems.map(function (wi) {
            return wi.id;
        });

        // Fetch the work items details
        var projectName = await IndexLibrary.GetCurrentProjectName();
        var items = await IndexLibrary
            .GetWorkItemsInDevops(recentWorkItemIds, projectName, [
                "System.Id",
                "System.Title",
                "System.State",
                "System.WorkItemType",
                "System.TeamProject",
            ]);

        // .then(function (items) {

        suggestionsHtml =
            "<div style='font-weight: 600; font-size:15px; height: 36px;  '> Recent work items </div>";
        var recentItems = items.slice(0, 5); // show only 5 recent items
        for (
            var suggestedItemIndex = 0;
            suggestedItemIndex < recentItems.length;
            suggestedItemIndex++
        ) {
            // var sDate = new Date(items[suggestedItemIndex].startDate);
            // var eDate = new Date(items[suggestedItemIndex].endDate);
            // var rowId =
            //     items[suggestedItemIndex].id +
            //     "_" +
            //     items[suggestedItemIndex].project;
            suggestionsHtml =
                suggestionsHtml +
                "<div class='work-item-suggestion' style='font-size:15px;height:30px;vertical-align:middle;cursor:pointer;padding:5px;border-radius:3px;' " +
                "data-workitem-id='" +
                recentItems[suggestedItemIndex].id +
                "' " +
                "data-workitem-title='" +
                (
                    recentItems[suggestedItemIndex].fields["System.Title"] || ""
                ).replace(/'/g, "&#39;") +
                "' " +
                "data-workitem-type='" +
                (recentItems[suggestedItemIndex].fields["System.WorkItemType"] ||
                    "") +
                "' " +
                "data-workitem-project='" +
                (recentItems[suggestedItemIndex].fields["System.TeamProject"] ||
                    "") +
                "' " +
                "data-workitem-state='" +
                (recentItems[suggestedItemIndex].fields["System.State"] || "") +
                "' " +
                "onclick='addWorkItemToFilter(this)'>";
            var workItemType =
                recentItems[suggestedItemIndex].fields["System.WorkItemType"] || "";
            var workItemTitle =
                recentItems[suggestedItemIndex].fields["System.Title"] || "";
            var workItemIcon =
                allWorkItemTypes.find((x) => x.name == workItemType)
                    ?.iconUrl || allWorkItemTypes[0]?.iconUrl;

            suggestionsHtml =
                suggestionsHtml +
                "<span class='search-suggestion-icon flex-row flex-noshrink'><img class='suggestion' src='" +
                workItemIcon +
                "' style='min-width: 14px;height: 14px;' /></span><span class='search-suggestion-title text-ellipsis' style='padding-left:8px'> " +
                workItemTitle +
                "</span> <span style='color: var(--text-secondary-color, rgba(0, 0, 0, .55));padding-left:8px'> #" +
                recentItems[suggestedItemIndex].id;
            suggestionsHtml = suggestionsHtml + "</span></div>";
        }
        $("#taskSuggestions").html(suggestionsHtml);
        $("#taskSuggestions").show();
        //})
        //.catch(function (error) {
        // console.error("Error fetching work items:", error);
        // $("#taskSuggestions").html(
        //     "<span><i>Error loading recent work items</i></span>"
        // );
        // $("#taskSuggestions").show();
        //});
    }

}

function AddOrRemoveWorkItem(item) {
    var itemIndex = selectedWorkItems.indexOf(
        parseInt(item.dataset["workitemId"])
    );

    if (itemIndex == -1) {
        selectedWorkItems.push(parseInt(item.dataset["workitemId"]));
        var title =
            item.dataset["workitemType"] + ": " + item.dataset["workitemTitle"];
        $("#txtFilter").val(title);
    } else {
        selectedWorkItems.splice(itemIndex, 1);
        $("#txtFilter").val("");
    }

}

function toggleRelatedWorkView() {
    const container = document.getElementById("list-related");
    if (!window._relatedWorkAll) return;

    window._relatedWorkExpanded = !window._relatedWorkExpanded;
    renderRelatedWorkItems(window._relatedWorkAll, window._relatedWorkExpanded, container);
}

async function showRelatedWorkItems(workItemId) {
    const container = document.getElementById("list-related");
    container.innerHTML = `<li class="list-group-item text-center text-muted small">Loading related work...</li>`;

    const grouped = await getRelatedWorkItems(workItemId);

    const allItems = Object.entries(grouped).flatMap(([group, items]) =>
        items.map((i) => ({ ...i, linkType: group }))
    );

    if (!allItems.length) {
        container.innerHTML = `<li class="list-group-item text-center text-muted small">No related work items found.</li>`;
        return;
    }

    // store global state
    window._relatedWorkAll = allItems;
    window._relatedWorkExpanded = false;

    renderRelatedWorkItems(allItems, false, container);
}

function buildStateColorMap(allWorkItemTypes) {
    const map = {};

    allWorkItemTypes.forEach(type => {
        if (!type?.name || !Array.isArray(type.states)) return;

        const typeKey = type.name.trim().toLowerCase();
        const stateMap = {};

        type.states.forEach(state => {
            if (!state?.name) return;

            const stateKey = state.name.trim().toLowerCase();

            stateMap[stateKey] = {
                color: state.color,
                category: state.category
            };
        });

        map[typeKey] = stateMap;
    });

    return map;
}




async function renderRelatedWorkItems(allItems, expanded = false, container) {
    const groupIndex = (type) =>
        GROUP_ORDER.indexOf(type) === -1 ? GROUP_ORDER.length : GROUP_ORDER.indexOf(type);

    // sort by group order + recency
    allItems.sort((a, b) => {
        const groupDiff = groupIndex(a.linkType) - groupIndex(b.linkType);
        if (groupDiff !== 0) return groupDiff;
        return new Date(b.updated) - new Date(a.updated);
    });

    const visible = expanded
        ? allItems
        : allItems.slice(0, RELATED_PAGE_SIZE);
    const hidden = expanded ? [] : allItems.slice(RELATED_PAGE_SIZE);

    const groupedVisible = {};
    visible.forEach((i) => {
        if (!groupedVisible[i.linkType]) groupedVisible[i.linkType] = [];
        groupedVisible[i.linkType].push(i);
    });

    let html = "";

    var projectName = await IndexLibrary.GetCurrentProjectName();
    var accountName = await IndexLibrary.GetAccountNameAsync();
    GROUP_ORDER.forEach((group) => {
        const items = groupedVisible[group];
        if (!items || !items.length) return;

        html += `<li class="list-group-item fw-bold border-bottom">${eaEscapeHtml(group)}</li>`;
        items.forEach((item) => {
            const workItemUrl = `https://dev.azure.com/${accountName}/${projectName}/_workitems/edit/${item.id}`;
            const iconUrl = allWorkItemTypes.find(x => x.name === item.type)?.iconUrl || "";
            const typeKey = item.type ? item.type.trim().toLowerCase() : "";
            const stateKey = item.state ? item.state.trim().toLowerCase() : "";

            let rawColor =
                workItemStateColorMap?.[typeKey]?.[stateKey]?.color;

            if (typeof rawColor === "string" && /^[0-9a-f]{6}$/i.test(rawColor)) {
                rawColor = `#${rawColor}`;
            }

            // Validate color
            const isLikelyColor = c =>
                typeof c === "string" && (/^#/i.test(c) || /^rgb\(/i.test(c));

            // Final state color (ADO-defined, safe fallback)
            const stateColor = isLikelyColor(rawColor)
                ? rawColor
                : "rgb(178, 178, 178)";


            const hasAssignedTo =
                item.assignedTo &&
                item.assignedTo.trim &&
                item.assignedTo.trim() !== "";

            const userInitials = hasAssignedTo
                ? (item.assignedTo.split(" ").length >= 2
                    ? (
                        item.assignedTo.split(" ")[0][0] +
                        item.assignedTo.split(" ")[1][0]
                    ).toUpperCase()
                    : item.assignedTo.substring(0, 2).toUpperCase())
                : "";

            const cleanState = item.state ? item.state.trim() : "";

            html += `
                <li class="list-group-item" style="padding: 0; overflow: hidden;">
                    <div class="removable-item-container full-width" style="display: flex; width: 100%; min-width: 0;">
                        <div class="artifact-link-container artifact-link padding-bottom-8"
                            style="flex: 1; padding: 8px; min-width: 0; overflow: hidden;">
                
                            <div class="flex-row flex-center artifact-link"
                                style="display: flex; align-items: center; flex-wrap: nowrap; min-width: 0;">
                
                                <img src="${eaSafeUrl(iconUrl)}" alt="${eaEscapeHtml(item.type)}"
                                    style="width: 16px; height: 16px; margin-right: 8px; flex-shrink: 0;" />
                
                                ${hasAssignedTo ? `
                                <div style="margin-right: 8px; flex-shrink: 0;">
                                    <div class="bolt-coin avatar-circle" aria-label="${eaEscapeHtml(item.assignedTo)}">
                                        ${eaEscapeHtml(userInitials)}
                                    </div>
                                </div>
                                ` : ""}
                
                                <div class="artifact-link-id secondary-text margin-right-4"
                                    style="margin-right: 4px; color: #666; font-size: 14px; flex-shrink: 0;">
                                    ${eaEscapeHtml(item.id)}
                                </div>
                
                                <a class="artifact-link-link bolt-link no-underline-link related-work-title"
                                href="${eaSafeUrl(workItemUrl)}"
                                target="_blank" rel="noopener noreferrer"
                                tabindex="0"
                                title="${eaEscapeHtml(item.title)}"
                                style="color: #0078d4; text-decoration: none; overflow: hidden;
                                        text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0;">
                                    ${eaEscapeHtml(item.title)}
                                </a>
                            </div>
                
                            <div class="artifact-details margin-left-16 flex-row flex-center"
                                style="margin-left: 16px; display: flex; align-items: center; margin-top: 4px;">
                
                                <span class="padding-right-8 text-ellipsis"
                                    style="padding-right: 8px; color: #000; font-size: 12px;">
                                    Updated <time class="bolt-time-item white-space-nowrap"
                                                style="white-space: nowrap;">${eaEscapeHtml(item.updated)}</time>
                                </span>
                
                            <span class="state-text"
                                    style="--state-color:${eaEscapeHtml(stateColor)}">
                                    ${eaEscapeHtml(cleanState)}
                                </span>
                            </div>
                        </div>
                    </div>
                </li>`;
        });
    });

    // Footer logic
    if (expanded) {
        html += `
                <li class="list-group-item text-center small text-primary"
                    style="cursor:pointer"
                    onclick="toggleRelatedWorkView()">
                    Show less
                </li>`;
    } else if (hidden.length > 0) {
        const hiddenByGroup = hidden.reduce((acc, cur) => {
            acc[cur.linkType] = (acc[cur.linkType] || 0) + 1;
            return acc;
        }, {});
        const notShownText = Object.entries(hiddenByGroup)
            .map(([k, v]) => `${k} (${v})`)
            .join(", ");

        html += `
                <li class="list-group-item text-center small text-primary"
                    style="cursor:pointer"
                    onclick="toggleRelatedWorkView()">
                    Show more (${visible.length} of ${allItems.length})
                </li>

                <li class="list-group-item text-center text-muted small">
                    Not shown: ${notShownText}
                </li>`;
    }

    container.innerHTML = html;
}


async function showAllRelatedItems() {
    const container = document.getElementById("list-related");
    const allItems = window._relatedWorkAll || [];
    if (!allItems.length) return;

    const grouped = {};
    allItems.forEach(i => {
        if (!grouped[i.linkType]) grouped[i.linkType] = [];
        grouped[i.linkType].push(i);
    });

    let html = "";
    var projectName = await IndexLibrary.GetCurrentProjectName();
    var orgName = await IndexLibrary.GetAccountNameAsync();
    GROUP_ORDER.forEach(group => {
        const items = grouped[group];
        if (!items || !items.length) return;

        html += `<li class="list-group-item fw-bold border-bottom">${eaEscapeHtml(group)}</li>`;
        items.forEach(item => {
            html += `
        <li class="list-group-item d-flex justify-content-between align-items-start">
          <div>
            <a href="https://dev.azure.com/${orgName}/${projectName}/_workitems/edit/${item.id}"
               target="_blank" class="fw-semibold text-decoration-none">${eaEscapeHtml(item.title)}</a>
            <div class="text-muted small">Updated ${eaEscapeHtml(item.updated)} • ${eaEscapeHtml(item.state)}</div>
          </div>
          <span class="badge bg-secondary ms-2">${eaEscapeHtml(item.type)}</span>
        </li>`;
        });
    });

    container.innerHTML = html;
}


async function getRelatedWorkItems(workItemId) {
    return new Promise(async (resolve, reject) => {
        try {
            //const workItem =  await witClient.getWorkItem(workItemId, null, null, 4);
            const workItem = await IndexLibrary.GetWorkItemWithRelations(workItemId);
            if (!workItem.relations) return resolve({});

            const groups = {}; // dynamic buckets

            // helper: get display name for link type
            const mapLinkType = (relString = "") => {
                const normalized = relString
                    .replace("System.LinkTypes.", "")
                    .toLowerCase();

                if (normalized.includes("hierarchy-reverse")) return "Parent";
                if (normalized.includes("hierarchy-forward")) return "Child";
                if (normalized.includes("dependency-reverse")) return "Predecessor";
                if (normalized.includes("dependency-forward")) return "Successor";
                if (normalized.includes("related")) return "Related";
                if (normalized.includes("duplicate-reverse")) return "Duplicate";
                if (normalized.includes("duplicate-forward")) return "Duplicate Of";
                if (normalized.includes("testedby-reverse")) return "Tests";
                if (normalized.includes("testedby-forward")) return "Tested By";
                return "Other";
            };


            // group IDs by link type
            for (const rel of workItem.relations) {
                if (!rel.url?.includes("/_apis/wit/workItems/")) continue;
                const id = parseInt(rel.url.split("/").pop());
                const label = mapLinkType(rel.rel);
                if (!groups[label]) groups[label] = [];
                groups[label].push(id);
            }

            // fetch all groups in parallel with FULL DETAILS
            const fields = [
                "System.Id", "System.Title", "System.State", "System.WorkItemType",
                "System.AssignedTo", "System.ChangedDate",
                "System.Description",
                "Microsoft.VSTS.Common.AcceptanceCriteria"
            ];

            const groupEntries = Object.entries(groups);
            const fetched = await Promise.all(groupEntries.map(async ([key, ids]) => {
                if (!ids.length) return [key, []];
                const items = await IndexLibrary.GetWorkItemsWithFields(ids, fields);
                return [key, items];
            }));

            // normalize output with full details
            const result = {};
            for (const [key, items] of fetched) {
                result[key] = items.map(i => ({
                    id: i.id,
                    title: i.fields["System.Title"],
                    state: i.fields["System.State"],
                    type: i.fields["System.WorkItemType"],
                    assignedTo: i.fields["System.AssignedTo"]?.displayName || null,
                    updated: new Date(i.fields["System.ChangedDate"]).toLocaleDateString("en-GB", { day: "numeric", month: "short" }),
                    linkType: key,
                    description: i.fields["System.Description"] || "",
                    acceptanceCriteria: i.fields["Microsoft.VSTS.Common.AcceptanceCriteria"] || ""
                }));
            }

            resolve(result);
        } catch (err) {
            // Error fetching related work items
            reject(err);
        }

    });
}

// Global variable to store selected work item for the filter (only one item allowed)
var selectedWorkItemForFilter = null;

async function addWorkItemToFilter(element) {
    var workItemId = element.getAttribute("data-workitem-id");
    var workItemTitle = element.getAttribute("data-workitem-title");
    var workItemType = element.getAttribute("data-workitem-type");
    var workItemProject = element.getAttribute("data-workitem-project");
    var workItemState = element.getAttribute("data-workitem-state");

    // Store basic info first
    selectedWorkItemForFilter = {
        id: workItemId,
        title: workItemTitle,
        type: workItemType,
        project: workItemProject,
        state: workItemState,
        description: "",
        acceptanceCriteria: ""
    };

    // Update the filter display
    updateFilterDisplay();

    // Hide the suggestions dropdown
    $("#taskSuggestions").hide();

    try {
        var fields = ["System.Id", "System.Title", "System.WorkItemType",
            "System.State", "System.TeamProject",
            "System.Description",
            "Microsoft.VSTS.Common.AcceptanceCriteria"];

        const workItem = await IndexLibrary.GetWorkItemWithFields(workItemId, fields);
        // Update with full details
        selectedWorkItemForFilter.description = workItem.fields["System.Description"] || "";
        selectedWorkItemForFilter.acceptanceCriteria = workItem.fields["Microsoft.VSTS.Common.AcceptanceCriteria"] || "";
    } catch (error) {
        // Error fetching work item details - continue with basic info
    }

    refreshRelatedOrGeneratedPanel();
}

function updateFilterDisplay() {
    var txtFilter = document.getElementById("txtFilter");
    var filterContainer = txtFilter.parentElement;

    // Remove existing work item display
    var existingDisplay = filterContainer.querySelector(".work-item-display");
    if (existingDisplay) {
        existingDisplay.remove();
    }

    if (selectedWorkItemForFilter) {
        // Hide the input and show work item display
        txtFilter.style.display = "none";

        // ✅ Get icon for the work item type
        var workItemType = selectedWorkItemForFilter.type;
        var iconUrl =
            allWorkItemTypes.find((x) => x.name === workItemType)?.iconUrl ||
            allWorkItemTypes[0]?.iconUrl;

        // Create work item display
        var workItemDisplay = document.createElement("div");
        workItemDisplay.className = "work-item-display";
        workItemDisplay.style.cssText = `
      display: flex;
      align-items: center;
      background: none;
      border: none;
      padding: 8px 15px;
      margin: 0;
      font-size: 14px;
      width: 100%;
      color: #333;
    `;

        workItemDisplay.innerHTML = `
      <span style="flex: 1;">
        <img src="${eaSafeUrl(iconUrl)}" style="width:16px;height:16px;margin-right:6px;vertical-align:middle;">
        ${eaEscapeHtml(selectedWorkItemForFilter.title)} #${eaEscapeHtml(selectedWorkItemForFilter.id)}
      </span>
      <span onclick="removeWorkItemFromFilter()" 
            style="cursor: pointer; font-weight: bold; color: #666; font-size: 16px; margin-left: 8px;">&times;</span>
    `;

        filterContainer.appendChild(workItemDisplay);
    } else {
        // Show the input field
        txtFilter.style.display = "block";
        txtFilter.placeholder = "Enter title to search for tasks";
    }
}

function removeWorkItemFromFilter() {
    selectedWorkItemForFilter = null;

    const list = document.getElementById("list-related");
    if (list) {
        list.innerHTML = `
    <li class="list-group-item text-center text-muted small">
      No item selected
    </li>`;
    }


    updateFilterDisplay();
    refreshRelatedOrGeneratedPanel();
}

function getSelectedWorkItemForFilter() {
    return selectedWorkItemForFilter;
}

function showSaveProjectModal() {
    // Check if SweetAlert is available
    if (typeof Swal === "undefined") {
        console.log("SweetAlert not available - using fallback prompt");
        const projectName = prompt("Enter project name:");
        if (!projectName || !projectName.trim()) {
            IndexLibrary.ShowToast('error', "Project name is required");
            return;
        }

        /**
         * Gets all active projects from the API
         * @returns {Promise} - Promise that resolves with the list of projects
         */

        // Call the API to create the project
        CreateEvolveAssistProject(projectName)
            .then(async (apiResult) => {
                await refreshProjectList();
            })
            .catch((error) => {
                console.error("Error creating project:", error);
                IndexLibrary.ShowToast('error', "Failed to create project. Please try again.");
            });
        return;
    }

    // Simple modal implementation using SweetAlert2
    Swal.fire({
        title: "New Project",
        html: `
            <div style="text-align: left;">
                <div style="margin-bottom: 25px; position: relative;">
                    <label style="display: block; font-weight: 600; color: #333; font-size: 14px; letter-spacing: 0.5px;">
                        Name <span style="color: #e74c3c; font-weight: bold; margin-left: 2px;">*</span>
                    </label>
                    <div style="position: relative;">
                        <input type="text" id="projectName" class="swal2-input" placeholder="Enter project name" 
                               style="width: 87%; 
                                      padding: 12px 16px; 
                                      border: 2px solid #e1e8ed; 
                                      border-radius: 8px; 
                                      font-size: 14px; 
                                      background: #fafbfc; 
                                      transition: all 0.3s ease;
                                      box-shadow: 0 2px 4px rgba(0,0,0,0.05);
                                      outline: none;">
                       
                    </div>
                    <div style="margin-top: 6px; font-size: 12px; color: #7f8c8d; font-style: italic;text-align:center;">
                        Choose a descriptive name for your project
                    </div>
                </div>
            </div>
        `,
        showCancelButton: true,
        confirmButtonText: "Save",
        confirmButtonColor: "#0078d4",
        customClass: {
            popup: "swal2-popup-custom",
        },
        preConfirm: () => {
            const projectName = document.getElementById("projectName").value;

            if (!projectName.trim()) {
                Swal.showValidationMessage("Project name is required");
                return false;
            }

            return {
                name: projectName,
            };
        },
    }).then(async (result) => {
        if (result.isConfirmed) {
            try {
                // Show loading state
                Swal.fire({
                    title: "Creating Project...",
                    text: "Please wait while we create your project",
                    allowOutsideClick: false,
                    showConfirmButton: false,
                    willOpen: () => {
                        Swal.showLoading();
                    },
                });

                // Call the API to create the project
                const apiResult = await CreateEvolveAssistProject(result.value.name);

                // Hide loading and show success
                Swal.fire({
                    title: "Success!",
                    text: "Project created successfully",
                    icon: "success",
                    confirmButtonColor: "#0078d4",
                });

                // Refresh the project list using the API
                try {
                    await refreshProjectList();
                } catch (refreshError) {
                    console.error("Error refreshing project list:", refreshError);
                    // Fallback: refresh the table with current data
                    PopulateEvolveAssistListTable();
                }
            } catch (error) {
                console.error("Error creating project:", error);

                // Hide loading and show error
                Swal.fire({
                    title: "Error!",
                    text: "Failed to create project. Please try again.",
                    icon: "error",
                    confirmButtonColor: "#d33",
                });
            }
        }
    });
}

async function NavigateToAssistList() {
    var orgName = await IndexLibrary.GetAccountNameAsync();
    var projectName = await IndexLibrary.GetCurrentProjectName();
    const config = await IndexLibrary.GetExtensionConfig();
    publisherId = config.publisherId;
    extensionId = config.extensionId;

    var newUrl =
        "https://dev.azure.com/" +
        orgName +
        "/" +
        projectName +
        "/_apps/hub/" +
        publisherId +
        "." +
        extensionId +
        ".release-groups-hub-group.list-evolve-assists";

    IndexLibrary.NavigateToUrl(newUrl);
}

function addTooltipsToPanel(panelType) {
    const listItems = document.querySelectorAll(
        `#list-${panelType} .list-group-item`
    );

    listItems.forEach((item) => {
        const icon = item.querySelector("img");
        if (!icon) {
            return;
        }
        icon.classList.add("tooltip-custom");
        const itemText = item.textContent.trim();
        let tooltipContent = itemText;
        if (item.hasAttribute("data-tooltip")) {
            tooltipContent = item.getAttribute("data-tooltip");
        } else if (itemText) {
            tooltipContent = itemText;
        } else {
            tooltipContent = "No description available";
        }

        const existingTooltip = icon.querySelector(".tooltip-text");
        if (existingTooltip) {
            existingTooltip.remove();
        }

        const tooltip = document.createElement("div");
        tooltip.className = "tooltip-text";
        tooltip.textContent = tooltipContent;
        tooltip.style.display = "none";

        document.body.appendChild(tooltip);

        icon.addEventListener("mouseenter", function (e) {
            const rect = icon.getBoundingClientRect();
            tooltip.style.display = "block";
            tooltip.style.position = "fixed";
            tooltip.style.left = rect.right + "px";
            tooltip.style.top = rect.top + "px";
            tooltip.style.zIndex = "9999";
        });

        icon.addEventListener("mouseleave", function (e) {
            tooltip.style.display = "none";
        });
    });
}

function initializeTooltips() {
    const suggestionsPanel = document
        .querySelector("#list-suggestions")
        .closest(".col-md-3");
    const acceptedPanel = document
        .querySelector("#list-accepted")
        .closest(".col-md-3");

    if (suggestionsPanel.classList.contains("panel-collapsed")) {
        addTooltipsToPanel("suggestions");
    }

    if (acceptedPanel.classList.contains("panel-collapsed")) {
        addTooltipsToPanel("accepted");
    }
}



makeSelectable("list-suggestions");
makeSelectable("list-accepted");

const listSuggestions = document.getElementById("list-suggestions");
const listAccepted = document.getElementById("list-accepted");

// Collapse functionality for both panels
function togglePanelCollapse(panelType) {
    const panel = document
        .querySelector(`#list-${panelType}`)
        .closest(".collapsible-panel");
    const chevron = document.getElementById(`${panelType}-chevron`);
    const isCollapsed = panel.classList.contains("panel-collapsed");

    if (isCollapsed) {
        panel.classList.remove("panel-collapsed");
        chevron.classList.remove("fa-angle-double-right");
        chevron.classList.add("fa-angle-double-left");

        const listItems = panel.querySelectorAll(".list-group-item");
        listItems.forEach((item) => {
            item.classList.remove("tooltip-custom");
            const tooltipText = item.querySelector(".tooltip-text");
            if (tooltipText) {
                tooltipText.remove();
            }
        });
    } else {
        panel.classList.add("panel-collapsed");
        chevron.classList.remove("fa-angle-double-left");
        chevron.classList.add("fa-angle-double-right");

        addTooltipsToPanel(panelType);
    }
}

// Function to add tooltip data to list items
function addTooltipToItems(containerId) {
    const container = document.getElementById(containerId);
    if (container) {
        const items = container.querySelectorAll(".list-group-item");
        items.forEach((item) => {
            const textElement =
                item.querySelector("span") ||
                item.childNodes[item.childNodes.length - 1];
            if (
                textElement &&
                textElement.textContent &&
                !item.hasAttribute("data-tooltip")
            ) {
                const tooltipText = textElement.textContent.trim();
                item.setAttribute("data-tooltip", tooltipText);
                item.setAttribute("title", tooltipText); // Fallback tooltip
            }
        });
    }
}

// Add tooltips to existing items
addTooltipToItems("list-suggestions");
addTooltipToItems("list-accepted");


// JavaScript-based tooltip
function createTooltip(element, text) {
    const tooltip = document.createElement("div");
    tooltip.className = "js-tooltip";
    // Build rich content like the provided design
    const safe = (text || "").replace(/</g, "&lt;").replace(/>/g, "&gt;");
    const lines = safe.split(/\r?\n/).filter(Boolean);
    const itemsHtml = lines
        .map(function (line) {
            return (
                '<li style="padding:6px 0;">' +
                '<span style="font-weight:400;">' +
                line +
                "</span>" +
                "</li>"
            );
        })
        .join("");
    tooltip.innerHTML =
        '<ul style="list-style:none;margin:0;padding:0;">' + itemsHtml + "</ul>";

    tooltip.style.cssText = `
      position: fixed;
      background: #ffffff;
      color: #000000;
      padding: 14px 16px;
      border-radius: 4px;
      font-size: 13px;
      white-space: normal;
      word-break: break-word;
      z-index: 9999;
      box-shadow: 0 8px 20px rgba(0,0,0,0.12);
      border: 1px solid #e6e6e6;
      pointer-events: none;
      display: none;
      width: 280px; /* fixed width like the design */
    `;
    document.body.appendChild(tooltip);

    // Create a left pointing arrow element
    const arrow = document.createElement("div");
    arrow.className = "js-tooltip-arrow";
    arrow.style.cssText = `
      position: fixed;
      width: 0; height: 0;
      border-top: 8px solid transparent;
      border-bottom: 8px solid transparent;
      border-right: 8px solid #ffffff;
      z-index: 9998;
      display: none;
    `;
    // Add a subtle border overlay for the arrow to match the box border
    const arrowBorder = document.createElement("div");
    arrowBorder.style.cssText = `
      position: fixed;
      width: 0; height: 0;
      border-top: 9px solid transparent;
      border-bottom: 9px solid transparent;
      border-right: 9px solid #e6e6e6;
      z-index: 9997;
      display: none;
    `;
    document.body.appendChild(arrowBorder);
    document.body.appendChild(arrow);
    tooltip._arrow = arrow;
    tooltip._arrowBorder = arrowBorder;
    return tooltip;
}

// Delegated tooltip handling so it works any time a panel is in collapsed state
function showItemTooltip(item) {
    const tooltipText =
        item.getAttribute("data-tooltip") || item.textContent.trim();
    if (!tooltipText) return;
    const tooltip = createTooltip(item, tooltipText);
    const img = item.querySelector("img");
    const rect = img ? img.getBoundingClientRect() : item.getBoundingClientRect();
    const tooltipLeft = rect.right; // flush with icon/item
    const tooltipTop = rect.top; // align tops
    tooltip.style.left = tooltipLeft + "px";
    tooltip.style.top = tooltipTop + "px";
    tooltip.style.transform = "none";
    tooltip.style.display = "block";
    item._tooltip = tooltip;
}

function hideItemTooltip(item) {
    if (item && item._tooltip) {
        item._tooltip.remove();
        item._tooltip = null;
    }
}

document.addEventListener("mouseover", function (e) {
    const li = e.target.closest(".list-group-item");
    if (!li) return;
    const card = li.closest(".card");
    if (!card || !card.classList.contains("collapsed")) return;
    // ensure tooltip for this item
    if (!li._tooltip) showItemTooltip(li);
});

document.addEventListener("mouseout", function (e) {
    const li = e.target.closest(".list-group-item");
    if (!li) return;
    // If moving outside the item, hide the tooltip
    if (!li.contains(e.relatedTarget)) hideItemTooltip(li);
});

// Add tooltips to dynamically added items
const observer = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
        if (mutation.type === "childList") {
            mutation.addedNodes.forEach(function (node) {
                if (
                    node.nodeType === 1 &&
                    node.classList &&
                    node.classList.contains("list-group-item")
                ) {
                    const textElement =
                        node.querySelector("span") ||
                        node.childNodes[node.childNodes.length - 1];
                    if (
                        textElement &&
                        textElement.textContent &&
                        !node.hasAttribute("data-tooltip")
                    ) {
                        node.setAttribute("data-tooltip", textElement.textContent.trim());
                    }
                }
            });
        }
    });
});

// Observe both suggestion and accepted lists
const suggestionsList = document.getElementById("list-suggestions");
const acceptedList = document.getElementById("list-accepted");

if (suggestionsList) {
    observer.observe(suggestionsList, { childList: true });
}
if (acceptedList) {
    observer.observe(acceptedList, { childList: true });
}

// ========== Conversational AI Chat Functions ==========

// Global variable to store conversation history
var conversationHistory = [];

/**
 * Extracts JSON suggestions object from a text message
 * @param {string} message - The message that may contain JSON
 * @returns {object|null} - The suggestions object if found, null otherwise
 */
function extractJSONSuggestions(message) {
    if (!message) {
        console.log("extractJSONSuggestions: No message provided");
        return null;
    }

    console.log("extractJSONSuggestions: Processing message of length", message.length);

    // Pattern 1: Look for ```json ... ``` code blocks (case insensitive)
    const jsonCodeBlockMatch = message.match(/```json\s*([\s\S]*?)```/i);
    if (jsonCodeBlockMatch) {
        console.log("Found ```json code block, attempting to parse...");
        try {
            const jsonContent = jsonCodeBlockMatch[1].trim();
            console.log("JSON content from code block:", jsonContent);
            const parsed = JSON.parse(jsonContent);
            if (parsed.Suggestions || parsed.suggestions) {
                return parsed;
            }
        } catch (e) {
        }
    }

    // Pattern 2: Look for ``` ... ``` code blocks (without language specifier)
    const codeBlockMatch = message.match(/```\s*([\s\S]*?)```/);
    if (codeBlockMatch) {
        console.log("Found ``` code block, attempting to parse...");
        try {
            const jsonContent = codeBlockMatch[1].trim();
            console.log("JSON content from generic code block:", jsonContent);
            const parsed = JSON.parse(jsonContent);
            if (parsed.Suggestions || parsed.suggestions) {
                return parsed;
            }
        } catch (e) {
        }
    }

    // Pattern 3: Look for { ... } JSON object with "Suggestions" key anywhere in text
    console.log("Searching for raw JSON object in message...");
    const openBraceIndex = message.indexOf('{');
    if (openBraceIndex !== -1) {
        // Find matching closing brace
        let braceCount = 0;
        let startIndex = openBraceIndex;
        let endIndex = -1;

        for (let i = startIndex; i < message.length; i++) {
            if (message[i] === '{') braceCount++;
            if (message[i] === '}') {
                braceCount--;
                if (braceCount === 0) {
                    endIndex = i + 1;
                    break;
                }
            }
        }

        if (endIndex !== -1) {
            try {
                const jsonString = message.substring(startIndex, endIndex);
                console.log("Found potential JSON object:", jsonString.substring(0, 100) + "...");
                const parsed = JSON.parse(jsonString);
                if (parsed.Suggestions || parsed.suggestions) {
                    return parsed;
                } else {
                }
            } catch (e) {
            }
        }
    }

    // Pattern 4: Try parsing the entire message as JSON (last resort)
    console.log("Attempting to parse entire message as JSON...");
    try {
        const parsed = JSON.parse(message.trim());
        if (parsed.Suggestions || parsed.suggestions) {
            return parsed;
        }
    } catch (e) {
    }

    return null;
}

function openChatDialog(initialUserMessage, aiResponse) {
    console.log("openChatDialog called");
    console.log("Initial user message:", initialUserMessage);
    console.log("AI response:", aiResponse);

    // Initialize conversation history
    conversationHistory = [
        { role: "user", content: initialUserMessage },
        { role: "assistant", content: aiResponse }
    ];

    console.log("Conversation history initialized:", conversationHistory);

    showChatWidget();
}

function showChatWidget() {
    console.log("showChatWidget called");

    const chatWidget = document.getElementById("chat-widget-container");
    const chatInput = document.getElementById("chat-widget-input");
    const sendBtn = document.getElementById("chat-widget-send");
    const closeBtn = document.getElementById("close-chat-widget");

    console.log("Chat widget elements:", {
        chatWidget: chatWidget ? "Found" : "NOT FOUND",
        chatInput: chatInput ? "Found" : "NOT FOUND",
        sendBtn: sendBtn ? "Found" : "NOT FOUND",
        closeBtn: closeBtn ? "Found" : "NOT FOUND"
    });

    if (!chatWidget) {
        console.error("ERROR: chat-widget-container element not found in DOM!");
        IndexLibrary.ShowToast('error', "Error: Chat widget not found. Please refresh the page.");
        return;
    }

    if (!chatInput || !sendBtn || !closeBtn) {
        console.error("ERROR: One or more chat widget elements not found!");
        IndexLibrary.ShowToast('error', "Error: Chat widget elements not found. Please refresh the page.");
        return;
    }

    // Show the chat widget
    chatWidget.style.display = "block";
    console.log("Chat widget display set to block");

    // Render initial messages
    renderChatMessages();

    // Focus on input field
    try {
        chatInput.focus();
    } catch (e) {
        console.error("Could not focus on chat input:", e);
    }

    // Remove existing event listeners to prevent duplicates
    const newSendBtn = sendBtn.cloneNode(true);
    sendBtn.parentNode.replaceChild(newSendBtn, sendBtn);

    const newCloseBtn = closeBtn.cloneNode(true);
    closeBtn.parentNode.replaceChild(newCloseBtn, closeBtn);

    const newChatInput = chatInput.cloneNode(true);
    chatInput.parentNode.replaceChild(newChatInput, chatInput);

    // Add event listener for send button
    document.getElementById("chat-widget-send").addEventListener("click", sendChatMessage);

    // Add event listener for Enter key (Ctrl+Enter to send)
    document.getElementById("chat-widget-input").addEventListener("keypress", (e) => {
        if (e.key === "Enter" && e.ctrlKey) {
            e.preventDefault();
            sendChatMessage();
        }
    });

    // Add event listener for close button
    document.getElementById("close-chat-widget").addEventListener("click", closeChatWidget);

    // Scroll to bottom of chat
    scrollChatToBottom();
}

function closeChatWidget() {
    const chatWidget = document.getElementById("chat-widget-container");
    chatWidget.style.display = "none";

    // Clear conversation history
    conversationHistory = [];
}

function renderChatMessages() {
    const container = document.getElementById("chat-messages-container");
    if (!container) return;

    let messagesHTML = "";

    conversationHistory.forEach((msg) => {
        const isUser = msg.role === "user";

        messagesHTML += `
      <div style="display: flex; justify-content: ${isUser ? 'flex-end' : 'flex-start'}; margin-bottom: 12px;">
        <div style="
          max-width: 75%;
          padding: 10px 14px;
          border-radius: 12px;
          background-color: ${isUser ? '#0d6efd' : '#f0f0f0'};
          color: ${isUser ? 'white' : '#333'};
          font-size: 14px;
          line-height: 1.4;
          word-wrap: break-word;
        ">
          ${eaEscapeHtml(msg.content)}
        </div>
      </div>
    `;
    });

    container.innerHTML = messagesHTML;
    scrollChatToBottom();
}

async function sendChatMessage() {
    const input = document.getElementById("chat-widget-input");
    const message = input.value.trim();

    if (!message) return;

    // Add user message to history
    conversationHistory.push({ role: "user", content: message });

    // Clear input
    input.value = "";

    // Show loading state
    const sendBtn = document.getElementById("chat-widget-send");
    sendBtn.disabled = true;
    sendBtn.innerHTML = '<div class="spinner-border spinner-border-sm" role="status" style="width: 20px; height: 20px; border-width: 2px;"></div>';

    // Update chat UI
    renderChatMessages();

    // Call API
    var projectId = (editEvolveId == null || editEvolveId == undefined || editEvolveId == "") ? 0 : parseInt(editEvolveId, 10);

    var DevOpsProjectId = await IndexLibrary.GetCurrentProjectId();
    var projectName = await IndexLibrary.GetCurrentProjectName();
    var organizationId = IndexLibrary.GetAccountId();
    var createdBy = IndexLibrary.GetUserEmail();

    const requestBody = {
        ProjectId: projectId,
        OrganizationId: organizationId,
        ConversationHistory: conversationHistory,
        DevOpsProjectId: DevOpsProjectId,
        DevOpsProjectName: projectName,
        CreatedBy: createdBy,
        SelectedSuggestionWorkItemTypes: getEffectiveSelectedTypes()
    };

    IndexLibrary.PostRequest({
        endpoint: "/api/EvolveAssist/Chat",
        body: requestBody
    })
        .then((res) => {
            if (!res.ok) {
                // Get error details
                return res.text().then(errorText => {
                    throw new Error(`HTTP ${res.status}: ${errorText}`);
                });
            }
            return res.json();
        })
        .then((data) => {
            // Re-enable send button
            sendBtn.disabled = false;
            sendBtn.innerHTML = '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3.4 20.4L20.85 12.92C21.66 12.57 21.66 11.43 20.85 11.08L3.4 3.6C2.74 3.31 2.01 3.8 2.01 4.51L2 9.12C2 9.62 2.37 10.05 2.87 10.11L17 12L2.87 13.88C2.37 13.95 2 14.38 2 14.88L2.01 19.49C2.01 20.2 2.74 20.69 3.4 20.4Z" fill="white"/></svg>';

            // Check if AI has generated suggestions (has enough context)
            if (!data.needsMoreContext && data.suggestions) {
                // Update editEvolveId and URL in all scenarios
                if (data.projectId) {
                    editEvolveId = data.projectId;
                    safeUpdateUrl(editEvolveId);
                }

                // Update the suggestion input with the summarized prompt
                if (data.summarizedPrompt) {
                    document.getElementById("suggestion_input").value = data.summarizedPrompt;
                }

                // Close chatbox and display suggestions
                closeChatWidget();
                displaySuggestions(data.suggestions);
                saveChatSuggestions({
                    projectId: data.projectId, queryContext: data.summarizedPrompt, suggestions: data.suggestions.Suggestions
                });
            } else {
                // Check if the message contains JSON suggestions
                const jsonSuggestions = extractJSONSuggestions(data.message);

                if (jsonSuggestions) {
                    // Update editEvolveId and URL in all scenarios
                    if (data.projectId) {
                        editEvolveId = data.projectId;
                        safeUpdateUrl(editEvolveId);
                    }

                    // Update the suggestion input with the summarized prompt
                    if (data.summarizedPrompt) {
                        document.getElementById("suggestion_input").value = data.summarizedPrompt;
                    }

                    // Close chatbox and display suggestions
                    closeChatWidget();
                    displaySuggestions(jsonSuggestions);
                } else {
                    // AI needs more info - add response to conversation and continue chatting
                    console.log("AI needs more context, continuing conversation.");
                    conversationHistory.push({ role: "assistant", content: data.message });

                    // Update UI
                    renderChatMessages();
                }
            }
        })
        .catch((err) => {
            console.error("Chat error:", err);
            console.error("Chat error message:", err.message);
            console.error("Conversation history:", conversationHistory);
            console.error("ProjectId:", projectId);
            console.error("OrganizationId:", organizationId);

            sendBtn.disabled = false;
            sendBtn.innerHTML = '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3.4 20.4L20.85 12.92C21.66 12.57 21.66 11.43 20.85 11.08L3.4 3.6C2.74 3.31 2.01 3.8 2.01 4.51L2 9.12C2 9.62 2.37 10.05 2.87 10.11L17 12L2.87 13.88C2.37 13.95 2 14.38 2 14.88L2.01 19.49C2.01 20.2 2.74 20.69 3.4 20.4Z" fill="white"/></svg>';

            IndexLibrary.ShowToast('error', "Failed to send message. Error: " + err.message);
        });
}

function scrollChatToBottom() {
    const container = document.getElementById("chat-messages-container");
    if (container) {
        container.scrollTop = container.scrollHeight;
    }
}

function displaySuggestions(suggestionsData) {
    console.log("displaySuggestions called with:", suggestionsData);
    const listEl = document.getElementById("list-suggestions");
    if (!listEl) {
        console.log("list-suggestions element not found!");
        return;
    }

    const suggestions = suggestionsData?.Suggestions || [];
    console.log("Extracted suggestions array:", suggestions);
    console.log("Suggestions length:", suggestions.length);

    if (!suggestions.length) {
        console.log("No suggestions to display");
        listEl.innerHTML =
            "<li class='list-group-item bg-gray'>No suggestions returned</li>";
        return;
    }

    // Generate HTML for suggestions
    const html = suggestions
        .map((item) => {
            // Handle both lowercase and Title case properties
            const title = item.title || item.Title || "";
            const desc = item.description || item.Description || "";
            const category = item.category || item.Category || item.type || item.Type || "Task";

            // Find appropriate icon
            const iconUrl =
                allWorkItemTypes.find((x) => x.name === category)?.iconUrl ||
                allWorkItemTypes[0]?.iconUrl;

            return `
        <li class="list-group-item bg-gray"
            data-category="${eaEscapeHtml(category)}"
            data-item='${eaEscapeHtml(JSON.stringify(item))}'
        >
          <img src="${eaSafeUrl(iconUrl)}" alt="${eaEscapeHtml(category)}" />
          <div style="flex: 1;">
            <strong>${eaEscapeHtml(title)}</strong>
            ${desc
                    ? `<div style="font-size: 12px; color: #666; margin-top: 2px;">${eaSanitizeRichText(desc)}</div>`
                    : ""
                }
          </div>
        </li>
      `;
        })
        .join("");

    listEl.innerHTML = html;
}

function updateScopeText(scopeLevel) {
    // Store the value in the global variable
    scopeLevelGlobal = parseInt(scopeLevel);

    // Update UI
    $("#scopeText").text(scopeLevelGlobal === 1 ? "The Project" : "The Organization");
}
async function savePanelState(clearAccepted = false) {
    const listSuggestions = document.getElementById("list-suggestions");
    const listAccepted = document.getElementById("list-accepted");

    const suggestions = Array.from(listSuggestions.children)
        .map(li => JSON.parse(li.dataset.item));

    acceptedsuggestions = clearAccepted
        ? null
        : Array.from(listAccepted.children)
            .map(li => li.dataset.item ? JSON.parse(li.dataset.item) : { title: li.innerText, category: "Task", description: "" });


    // Build body
    const saveStateBody = {
        ProjectId: editEvolveId,
        QueryContext: document.getElementById("suggestion_input").value,
        LinkedItem: selectedWorkItemForFilter
            ? JSON.stringify({
                id: selectedWorkItemForFilter.id,
                title: selectedWorkItemForFilter.title,
                type: selectedWorkItemForFilter.type
            })
            : null,
        Suggestions: JSON.stringify(suggestions),
        AcceptedSuggestion: acceptedsuggestions ? JSON.stringify(acceptedsuggestions) : null,
        FilterTypes: workItemTypesParam,
        FilterStates: workItemStatesParam,
        SuggestionsHistory: suggestionsHistory.length > 0 ? JSON.stringify(suggestionsHistory) : null
    };

    await IndexLibrary.PostRequest({
        endpoint: "/api/EvolveAssist/SaveEvolveAssistState",
        body: saveStateBody
    });

    // Reload project data after saving to refresh all state including history
    if (editEvolveId) {
        await loadProjectData(editEvolveId, false);
    }
}
async function saveChatSuggestions({ projectId, queryContext, suggestions }) {
    if (!projectId || !queryContext || !suggestions) return;

    const linkedItem = selectedWorkItemForFilter
        ? {
            id: selectedWorkItemForFilter.id,
            title: selectedWorkItemForFilter.title,
            type: selectedWorkItemForFilter.type
        }
        : null;

    const saveStateBody = {
        ProjectId: projectId,
        QueryContext: queryContext,
        LinkedItem: linkedItem ? JSON.stringify(linkedItem) : null,
        Suggestions: JSON.stringify(suggestions),
        AcceptedSuggestion: (acceptedsuggestions && acceptedsuggestions.length > 0)
            ? JSON.stringify(acceptedsuggestions)
            : null,
        FilterTypes: workItemTypesParam,
        FilterStates: workItemStatesParam
    };

    try {
        const res = await IndexLibrary.PostRequest({
            endpoint: "/api/EvolveAssist/SaveEvolveAssistState",
            body: saveStateBody
        });

        if (!res.ok) {
            const text = await res.text();
            throw new Error(`Save state failed: ${text}`);
        }
    } catch (err) {
        console.error("Error saving EvolveAssist state:", err);
    }
}
function clearAcceptedList() {
    const listAccepted = document.getElementById("list-accepted");
    listAccepted.innerHTML = "";
    savePanelState(true);
}

function populateTaskTypeAndStatusDropdowns() {

    var workItemTypeFilterHtml = "";
    var workItemStateFilterHtml = "";
    var alreadyPopulatedWorkItems = [];

    allWorkItemTypes.forEach((element) => {
        workItemTypeFilterHtml =
            workItemTypeFilterHtml +
            "<div class='form-check'><input class='form-check-input chkWorkItemFilter' type='checkbox' id='chkWorkItemFilter' data-work-item-type='" +
            element.name +
            "'>";
        workItemTypeFilterHtml =
            workItemTypeFilterHtml +
            "<img src='" +
            element.iconUrl +
            "' style=' width: 14px;min-width: 14px;height: 14px;' />";
        workItemTypeFilterHtml =
            workItemTypeFilterHtml +
            "<label class='form-check-label' for='chkWorkItemFilter' style='font-size:14px; padding-left:5px'>";
        workItemTypeFilterHtml =
            workItemTypeFilterHtml + element.name;
        workItemTypeFilterHtml =
            workItemTypeFilterHtml + "</label></div>";

        element.states.forEach((stateElement) => {
            if (
                !alreadyPopulatedWorkItems.includes(
                    stateElement.name
                )
            ) {
                workItemStateFilterHtml =
                    workItemStateFilterHtml +
                    "<div class='form-check'><input class='form-check-input chkWorkItemStateFilter' type='checkbox' id='chkWorkItemStateFilter' data-work-item-state='" +
                    stateElement.name +
                    "'>";
                workItemStateFilterHtml =
                    workItemStateFilterHtml +
                    "<label class='form-check-label' for='chkWorkItemStateFilter' style='font-size:14px; padding-left:5px'>";
                workItemStateFilterHtml =
                    workItemStateFilterHtml + stateElement.name;
                workItemStateFilterHtml =
                    workItemStateFilterHtml + "</label></div>";
                alreadyPopulatedWorkItems.push(
                    stateElement.name
                );
            }
        });
    });

    $("#ddlWorkItemTypeFilter").html(workItemTypeFilterHtml);
    $("#ddlWorkItemStatusFilter").html(workItemStateFilterHtml);

    // Attach change handlers (only once)
    $(document).off("change", ".chkWorkItemFilter");
    $(document).on("change", ".chkWorkItemFilter", function () {
        let type = $(this).data("work-item-type");
        if ($(this).is(":checked")) {
            if (!selectedWorkItemTypesFilter.includes(type)) {
                selectedWorkItemTypesFilter.push(type);
            }
        } else {
            selectedWorkItemTypesFilter = selectedWorkItemTypesFilter.filter(
                (x) => x !== type
            );
        }
        GetWorkItemSuggestions(); // refresh results
    });

    $(document).off("change", ".chkWorkItemStateFilter");
    $(document).on("change", ".chkWorkItemStateFilter", function () {
        let status = $(this).data("work-item-state");
        if ($(this).is(":checked")) {
            if (!selectedWorkItemStatesFilter.includes(status)) {
                selectedWorkItemStatesFilter.push(status);
            }
        } else {
            selectedWorkItemStatesFilter = selectedWorkItemStatesFilter.filter(x => x !== status);
        }
        GetWorkItemSuggestions(); // refresh results
    });
}

/**
 * Load allowed suggestion work item types from backend configuration
 */
async function loadAllowedSuggestionTypes() {
    try {
        const response = await IndexLibrary.GetRequest({
            endpoint: "/api/Settings/GetEvolveConfigurations",
        });

        if (!response.ok) {
            console.error("Failed to load Evolve configurations");
            return;
        }

        const data = await response.json();

        // Parse the evolveWorkItemTypes from the response
        // Backend returns: { evolveWorkItemTypes: "User Story,Bug,Task" }
        if (data && data.evolveWorkItemTypes) {
            // Parse comma-separated list
            allowedSuggestionWorkItemTypes = data.evolveWorkItemTypes
                .split(",")
                .map((type) => type.trim())
                .filter((type) => type.length > 0);
        } else {
            // Default to all work item types if not configured
            allowedSuggestionWorkItemTypes = allWorkItemTypes.map((t) => t.name);
        }

        // Populate Task Type and Task Status dropdowns with filtered types
        populateTaskTypeAndStatusDropdowns();

        // Initialize the suggestion type filter
        initializeSuggestionTypeFilter();
    } catch (error) {
        console.error("Error loading allowed suggestion types:", error);
        // Default to all types on error
        allowedSuggestionWorkItemTypes = allWorkItemTypes.map((t) => t.name);
        populateTaskTypeAndStatusDropdowns();
        initializeSuggestionTypeFilter();
    }
}

/**
 * Initialize suggestion type filter from sessionStorage or defaults
 */
function initializeSuggestionTypeFilter() {
    // Get valid project work item type names
    const projectTypeNames = allWorkItemTypes.map((t) => t.name);

    // Filter org-allowed types to only include types that exist in the project
    const validAllowedTypes = allowedSuggestionWorkItemTypes.filter((type) =>
        projectTypeNames.includes(type)
    );

    // Load from sessionStorage if available
    const savedTypes = sessionStorage.getItem("selectedSuggestionWorkItemTypes");

    if (savedTypes) {
        try {
            const parsedTypes = JSON.parse(savedTypes);
            // Validate saved types against BOTH org settings AND project types
            selectedSuggestionWorkItemTypes = parsedTypes.filter((type) =>
                validAllowedTypes.includes(type)
            );

            // If all saved types were removed, default to valid allowed types
            if (selectedSuggestionWorkItemTypes.length === 0) {
                selectedSuggestionWorkItemTypes = [...validAllowedTypes];
            }

            saveSuggestionTypeSelection();
        } catch (e) {
            console.error("Error parsing saved suggestion types:", e);
            selectedSuggestionWorkItemTypes = [...validAllowedTypes];
        }
    } else {
        // Default to valid allowed types (intersection of org settings and project types)
        selectedSuggestionWorkItemTypes = [...validAllowedTypes];
    }

    // Populate the dropdown
    populateSuggestionTypeDropdown();
}

/**
 * Populate the suggestion type filter dropdown with checkboxes
 */
function populateSuggestionTypeDropdown() {

    let dropdownHtml = "";

    // Filter allWorkItemTypes to only show allowed types
    const allowedTypes = allWorkItemTypes.filter((type) =>
        allowedSuggestionWorkItemTypes.includes(type.name)
    );

    if (allowedTypes.length === 0) {
        console.warn("No allowed types found for suggestion filter dropdown!");
    }

    allowedTypes.forEach((type) => {
        const isChecked = selectedSuggestionWorkItemTypes.includes(type.name)
            ? "checked"
            : "";

        dropdownHtml += `
            <div class='form-check'>
                <input class='form-check-input chkSuggestionTypeFilter'
                       type='checkbox'
                       data-work-item-type='${type.name}'
                       ${isChecked}>
                <img src='${type.iconUrl}' style='width: 14px; height: 14px;' />
                <label class='form-check-label' style='font-size:14px; padding-left:5px'>
                    ${type.name}
                </label>
            </div>
        `;
    });

    console.log("Setting dropdown HTML, length:", dropdownHtml.length);
    $("#ddlSuggestionWorkItemTypeFilter").html(dropdownHtml);

    // Attach change handler
    $(document).off("change", ".chkSuggestionTypeFilter");
    $(document).on("change", ".chkSuggestionTypeFilter", function () {
        const type = $(this).data("work-item-type");

        if ($(this).is(":checked")) {
            if (!selectedSuggestionWorkItemTypes.includes(type)) {
                selectedSuggestionWorkItemTypes.push(type);
            }
        } else {
            selectedSuggestionWorkItemTypes = selectedSuggestionWorkItemTypes.filter(
                (x) => x !== type
            );
        }

        // Save to sessionStorage
        saveSuggestionTypeSelection();
    });
}


/**
 * Save suggestion type selection to sessionStorage
 */
function saveSuggestionTypeSelection() {
    sessionStorage.setItem(
        "selectedSuggestionWorkItemTypes",
        JSON.stringify(selectedSuggestionWorkItemTypes)
    );
}

function toggleFilters() {
    const bar = document.getElementById("filterBar");
    bar.classList.toggle("filter-hidden");
    bar.classList.toggle("filter-visible");
}

/**
 * Render suggestions history
 */
function renderSuggestionsHistory() {
    if (!suggestionsHistory || suggestionsHistory.length === 0) {
        $("#suggestions-history-container").hide();
        return;
    }

    $("#suggestions-history-container").show();
    $("#history-count").text(suggestionsHistory.length);

    const historyListEl = $("#suggestions-history-list");
    historyListEl.empty();

    suggestionsHistory.forEach((historyItem, index) => {
        // Each historyItem is an array of suggestions or an object with Suggestions property
        let suggestions = historyItem;

        // Handle both array format and object format
        if (historyItem.Suggestions) {
            suggestions = historyItem.Suggestions;
        }

        if (!Array.isArray(suggestions)) {
            console.error("Invalid history item format:", historyItem);
            return;
        }

        // Create a container for this history set
        const historySetDiv = $("<div>").css({
            "margin-bottom": "15px",
            "padding": "10px",
            "background-color": "#fafafa",
            "border-radius": "4px"
        });

        // Render suggestions in this history set (matching current suggestions style)
        suggestions.forEach((suggestion) => {
            const title = suggestion.title || suggestion.Title || "";
            const description = suggestion.description || suggestion.Description || "";
            const category = suggestion.category || suggestion.Category || suggestion.type || suggestion.Type || "Task";

            // Find appropriate icon (same as current suggestions)
            const iconUrl =
                allWorkItemTypes.find((x) => x.name === category)?.iconUrl ||
                allWorkItemTypes[0]?.iconUrl;

            const suggestionItem = $(`
                <li class="list-group-item bg-gray" data-category="${eaEscapeHtml(category)}"
                    data-item='${eaEscapeHtml(JSON.stringify(suggestion))}'>
                    <img src="${eaSafeUrl(iconUrl)}" alt="${eaEscapeHtml(category)}" />
                    <div style="flex: 1;">
                        <strong>${eaEscapeHtml(title)}</strong>
                        ${description ? `<div style="font-size: 12px; color: #666; margin-top: 2px;">${eaSanitizeRichText(description)}</div>` : ""}
                    </div>
                </li>
            `);

            historySetDiv.append(suggestionItem);
        });

        historyListEl.append(historySetDiv);
    });

    // Setup event handlers for history checkboxes
    setupHistoryCheckboxHandlers();
}

/**
 * Setup event handlers for history suggestions (make them selectable like current suggestions)
 */
function setupHistoryCheckboxHandlers() {
    $("#suggestions-history-list .list-group-item").on("click", function (e) {
        $(this).toggleClass("active");
    });
}

/**
 * Toggle suggestions history visibility
 */
$(document).ready(function () {
    $("#suggestions-history-toggle").on("click", function () {
        const content = $("#suggestions-history-content");
        const icon = $("#history-toggle-icon");
        const text = $("#history-toggle-text");

        if (content.is(":visible")) {
            content.slideUp(200);
            icon.removeClass("fa-angle-up").addClass("fa-angle-down");
            text.html(`View Previous Suggestions (<span id="history-count">${suggestionsHistory.length}</span>)`);
        } else {
            content.slideDown(200);
            icon.removeClass("fa-angle-down").addClass("fa-angle-up");
            text.html(`Hide Previous Suggestions`);
        }
    });
});

async function applyCreateWorkItemsPermission() {
    try {
        licensedUserType = await IndexLibrary.GetUserLicensesType(fieldName);

    } catch (err) {
        console.error("Failed to apply New Chat permission:", err);

    }
}
async function navigateToCreateProject() {
    var orgName = await IndexLibrary.GetAccountNameAsync();
    var projectName = await IndexLibrary.GetCurrentProjectName();

    var newUrl = "https://dev.azure.com/" + orgName + "/" + projectName + "/_apps/hub/" + publisherId + "." + extensionId + ".release-groups-hub-group.create-evolve-assist";

    await IndexLibrary.NavigateToUrl(newUrl);
}

async function getStoredRequiredFieldDefaults() {
    const orgId = IndexLibrary.GetAccountId();
    const projectId = await IndexLibrary.GetCurrentProjectId();
    const storageKey = `wit-defaults-${orgId}-${projectId}`;

    try {
        const stored = localStorage.getItem(storageKey);
        return stored ? JSON.parse(stored) : {};
    } catch (e) {
        return {};
    }
}

function toRequiredFieldDefaultsMap(savedDefaults) {
    const map = {};
    (savedDefaults || []).forEach(f => {
        if (f.defaultValue && f.defaultValue.trim() !== '') {
            map[f.referenceName] = f.defaultValue;
        }
    });
    return map;
}

function filterRequiredFieldsMissingDefaults(fields, savedDefaultsMap) {
    return fields.filter(f => {
        if (f.referenceName === 'System.Title') return false;
        if (f.referenceName === 'System.State') return false;
        if (savedDefaultsMap[f.referenceName]) return false;
        if (f.defaultValue !== undefined && f.defaultValue !== null && f.defaultValue !== '') return false;
        return true;
    });
}

/**
 * @param {object} requiredFieldsByWit - Fields grouped by WIT from DB
 * @param {object} defaultsByWit - Default values by WIT
 * @returns {object} - Formatted witGroups ready for popup display
 */
async function prepareRequiredFieldGroupsForPopup(requiredFieldsByWit, defaultsByWit) {
    if (!requiredFieldsByWit || Object.keys(requiredFieldsByWit).length === 0) {
        return {};
    }

    const witGroups = {};

    for (const witName in requiredFieldsByWit) {
        const fields = requiredFieldsByWit[witName];
        if (!fields || fields.length === 0) continue;

        const defaultsMap = (defaultsByWit && defaultsByWit[witName]) || {};

        witGroups[witName] = {
            fields: fields,
            defaultsMap: defaultsMap
        };
    }

    return witGroups;
}

/**
 * @param {object} missingByWit - Required fields missing defaults, grouped by WIT
 * @param {Array} workItemTypes - All work item types with icons
 * @param {object} defaultsByWit - Default values by WIT
 */
async function showRequiredFieldsPopupWithDefaults(missingByWit, workItemTypes, defaultsByWit = {}) {
    const witGroups = await prepareRequiredFieldGroupsForPopup(missingByWit, defaultsByWit);

    if (Object.keys(witGroups).length === 0) {
        return null;
    }

    return showRequiredFieldsPopupForMultipleWITs(witGroups, workItemTypes, false);
}

async function fetchConfigurableFieldsByWitFromProjectDb(projectId, witNames = [], filterChatId = null) {
    if (!projectId || !witNames || witNames.length === 0) return {};
    const orgName = organizationName || await IndexLibrary.GetAccountNameAsync();
    const classification = await rfFetchFieldClassification(orgName, azureAuthenticationHeader);
    const fieldsByWit = {};
    await Promise.all([...new Set(witNames)].map(async (wit) => {
        try {
            const res = await fetch(`https://dev.azure.com/${orgName}/${encodeURIComponent(projectId)}/_apis/wit/workitemtypes/${encodeURIComponent(wit)}/fields?$expand=allowedValues&api-version=7.0`,
                { headers: { Authorization: `Bearer ${azureAuthenticationHeader}` } });
            if (!res.ok) return;
            const fields = ((await res.json()).value || []).filter((f) => {
                const meta = classification[f.referenceName];
                return f.alwaysRequired && !(meta && meta.readOnly) && !EA_NON_FORM_FIELDS.has(f.referenceName);
            });
            if (fields.length) {
                fieldsByWit[wit] = fields.map((f) => {
                    const meta = classification[f.referenceName];
                    return {
                        name: f.name,
                        referenceName: f.referenceName,
                        type: rfResolveFieldType(meta),
                        isIdentity: !!(meta && meta.isIdentity),
                        alwaysRequired: true,
                        readOnly: !!(meta && meta.readOnly),
                        allowedValues: Array.isArray(f.allowedValues) ? f.allowedValues : []
                    };
                });
            }
        } catch (e) { }
    }));
    if (Object.keys(fieldsByWit).some((w) => fieldsByWit[w].some((f) => f.type === 'identity'))) {
        await rfFetchIdentityPeople(orgName, azureAuthenticationHeader);
    }
    return fieldsByWit;
}