var indexApp;
var baseAPIUrl = '';
var billingTypeFilter = "All";
var workTypeFilter = [];
var licensedUserType = ''
var isOrglicenseExpired = false;
var azureAuthenticationHeader = '';
var userguidelink = "";
var userhelplink = "";
var organizationName = "";

function escapeHtml(value) {
    if (IndexLibrary && IndexLibrary.escapeHtml) {
        return IndexLibrary.escapeHtml(value);
    }

    return String(value == null ? "" : value)
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#39;");
}

function showReportsTrialPill(message) {
    $("#reportsTrialPillText").text(message);
    $("#reportsTrialPill").show();
    $("#startTrialMessage").hide();
}

function hideReportsTrialPill() {
    $("#reportsTrialPill").hide();
}

let currentSortColumn = -1;
let currentSortOrder = 'asc';
const fieldName = "ptUserType";
let currentReportPage = 1;
let reportTotalPages = 1;
let reportPageSize = 0;
let reportTotalCount = 0;
IndexLibrary.InitializeSDK().then(async function () {
    azureAuthenticationHeader = await IndexLibrary.GetAccessToken();
    LoadApp();
})

function setButtonState(buttonSelector, isEnabled) {
    const btn = $(buttonSelector);
    if (btn.length) {
        btn.prop('disabled', !isEnabled);
        btn.css('opacity', isEnabled ? '1' : '0.5');
        btn.css('cursor', isEnabled ? 'pointer' : 'not-allowed');
        btn.css('pointer-events', isEnabled ? 'auto' : 'auto');
    }
}

$(document).ready(function () {
    setButtonState("#ddlTemplates", false);
    setButtonState("#btnReportingTemplates", false);
    $("#btnReportingTemplates_Wrapper").attr('title', 'Reporting templates are only available to manager roles.')
    $("#ddlTemplates").attr('title', 'Reporting templates are only available to manager roles.')

});
async function LoadApp() {
    try {
        hideReportsTrialPill();
        const config = await IndexLibrary.GetExtensionConfig();
        baseAPIUrl = config.apiBaseUrl;
        userguidelink = config.userguidelink;
        userhelplink = config.userhelplink;
        organizationName = await IndexLibrary.GetAccountNameAsync();

        await LoadWorkTypes();

        const getLicenseRequest = { organizationName: organizationName };
        const licenseResponse = await IndexLibrary.PostRequest({
            endpoint: '/api/License/GetLicense',
            body: getLicenseRequest
        });

        if (licenseResponse.status === 404) {
            hideReportsTrialPill();
            $("#startTrialMessage").show();
            CreateTrialLicense();
            $("#main").hide();
            return;
        }

        const licenseData = await licenseResponse.json();

        if (licenseData.status !== undefined && licenseData.status === 404) {
            hideReportsTrialPill();
            $("#startTrialMessage").show();
            CreateTrialLicense();
            $("#main").hide();
        } else {
            const isUserLicensedResponse = await IndexLibrary.GetRequest({
                endpoint: `/api/License/IsUserLicensed?organizationName=${organizationName}&email=${IndexLibrary.GetUserEmail()}&moduleUserType=ptUserType`
            });
            const isUserLicensed = await isUserLicensedResponse.text();

            if (isUserLicensed.toLowerCase() == 'false') {
                hideReportsTrialPill();
                $("#authorizationErrorMessage").show();
                $("#authorizationErrorMessage").text("You are not authorized to perform this action. Please contact your organization administrator.");
                $("#startTrialMessage").hide();
                $("#main").hide();
            } else {
                // Check if license is expired
                if (licenseData.expiryDateTimeUtc) {
                    const expiryDate = new Date(licenseData.expiryDateTimeUtc);
                    const today = new Date();
                    isOrglicenseExpired = today > expiryDate;
                }

                if (licenseData.licenseType === 0) {
                    const licenseExpiryDate = new Date(licenseData.expiryDateTimeUtc);
                    if (isOrglicenseExpired) {
                        hideReportsTrialPill();
                        $("#startTrialMessage").show();
                        $("#startTrialMessage").text("Your license is invalid or expired. Please contact your organization administrator.");
                    } else {
                        showReportsTrialPill("Trial till " + licenseExpiryDate.toLocaleDateString("en-US"));
                    }
                } else {
                    hideReportsTrialPill();
                    $("#startTrialMessage").hide();
                }
                await LoadReportPage();
                await PopulateTemplatesDropdown();
            }

        }


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



    } catch (error) {
        console.error("Error loading app:", error);
        hideReportsTrialPill();
        $("#startTrialMessage").show();
        $("#main").hide();
    }
}


async function CreateTrialLicense() {

    await IndexLibrary.AutoCreateTrialLicense();
}



async function LoadReportPage() {
    await SetupPermissions();
    $("#main").show();
    $("#userSuggestions").hide();
    $("#reportFromDate").datepicker();
    $("#reportToDate").datepicker();
    $("#chkAllBillingTypesFilter").on('click', function () {
        if ($(this).is(":checked")) {
            $("#chkBillableTypeFilter").prop("checked", false);
            $("#chkNonBillableTypeFilter").prop("checked", false);
        } else {
            $("#chkAllBillingTypesFilter").prop("checked", true);
        }
    })
    $("#chkBillableTypeFilter").on('click', function () {
        if ($(this).is(":checked")) {
            $("#chkAllBillingTypesFilter").prop("checked", false);
            $("#chkNonBillableTypeFilter").prop("checked", false);
        } else {
            $("#chkBillableTypeFilter").prop("checked", true);
        }
    })
    $("#chkNonBillableTypeFilter").on('click', function () {
        if ($(this).is(":checked")) {
            $("#chkAllBillingTypesFilter").prop("checked", false);
            $("#chkBillableTypeFilter").prop("checked", false);
        } else {
            $("#chkNonBillableTypeFilter").prop("checked", true);
        }
    })
    SetDefaultDateRangeFilter();
    let userSearchTimeout;

    $("#txtUserFilter").on("keyup", function () {
        clearTimeout(userSearchTimeout);
        const query = $(this).val().trim();

        if (query === "") {
            $(this).data('email', '');
            $("#userSuggestions").html("").hide();
            return;
        }

        userSearchTimeout = setTimeout(async () => {
            $("#txtUserFilter").data('email', '');
            const url = `https://vssps.dev.azure.com/${await IndexLibrary.GetAccountNameAsync()}/_apis/graph/users?api-version=7.0-preview.1`;

            fetch(url, {
                headers: { Authorization: "Bearer " + azureAuthenticationHeader }
            })
                .then(response => response.json())
                .then(json => {
                    const filteredUsers = json.value.filter(u =>
                        (u.origin === "aad" || u.origin === "msa") &&
                        u.displayName.toLowerCase().includes(query.toLowerCase())
                    );

                    if (filteredUsers.length === 0) {
                        $("#userSuggestions").html("<i>No matching users found</i>").show();

                        return;
                    }

                    let html = `
                <table style="width:100%">
                    <tr><th>Display Name</th><th>E-mail</th></tr>
                    ${filteredUsers.map(user => `
                        <tr style="cursor:pointer"
                            onclick="SelectUserFromSuggestion(this)"
                            data-display-name="${escapeHtml(user.displayName)}"
                            data-email="${escapeHtml(user.mailAddress || '')}">
                            <td>${escapeHtml(user.displayName)}</td>
                            <td>${escapeHtml(user.mailAddress || '')}</td>
                        </tr>
                    `).join("")}
                </table>
            `;

                    $("#userSuggestions").html(html);
                    $("#userSuggestions").show();
                })
                .catch(error => {
                    console.error("Error fetching users:", error);
                    $("#userSuggestions").html("<i>Error loading suggestions</i>").show();
                });
        }, 300); // Debounce: wait 300ms after typing
    });

    $(document).on('click', function (e) {
        if (!e.target.classList.contains('suggestion') && e.target.id !== 'txtUserFilter') {
            $("#userSuggestions").hide();
        }
    });
    $(".chkBillingType").on('click', function () {
        billingTypeFilter = $(this).data('billingType');
    });

    $("#btnGenerateReport").on('click', async function () {
        await GenerateTimesheetReport();
    });
}

async function GenerateTimesheetReport(page = 1) {
    $("#loadingSpinner").show();
    $("#reportContainer").hide();

    const accountName = await IndexLibrary.GetAccountNameAsync();
    const accountId = await IndexLibrary.GetAccountIdAsync();
    const userEmail = (licensedUserType === 0 || licensedUserType === "")
        ? IndexLibrary.GetUserEmail()
        : $("#txtUserFilter").data('email');

    try {
        const project = await IndexLibrary.GetCurrentProjectName();
        const startDate = $("#reportFromDate").val();
        const endDate = $("#reportToDate").val();
        const reportResponse = await IndexLibrary.PostRequest({
            endpoint: '/api/Timesheet/Report',
            body: {
                userEmail: userEmail,
                billingType: billingTypeFilter,
                workType: workTypeFilter,
                dateFrom: IndexLibrary.convertLocalToUtc(startDate),
                dateTo: IndexLibrary.convertLocalToUtc(endDate),
                organizationName: accountName,
                project: project,
                licensedUserType: licensedUserType,
                generatedBy: IndexLibrary.GetUserEmail(),
                templateId: parseInt($("#ddlTemplates").val()) || 0,
                page: page
            }
        });

        if (!reportResponse.ok) throw new Error("Failed to fetch report data.");

        const reportData = await reportResponse.json();
        currentReportPage = reportData.page || page;
        reportTotalPages = reportData.totalPages || 0;
        reportPageSize = reportData.pageSize || 0;
        reportTotalCount = reportData.totalCount || 0;

        if (reportData.values.length === 0) {
            $("#reportContainer").html("<span><i>No timesheet records found for selected criteria</i></span>");
            $("#reportPagingContainer").empty();
            return;
        }

        let headerHtml = '';
        for (var i = 0; i < reportData.columnNames.length; i++) {
            headerHtml += `<th onclick="sortTable(${i})">${escapeHtml(reportData.columnNames[i])}</th>`
        }
        let reportHtml = `
                <table id='reportTable' style='width:100%;margin-top:20px'>
                    <thead>
                        <tr>
                            ${headerHtml}<th></th>
                        </tr>
                    </thead>
                    <tbody>
            `;

        const idColumnIndex = reportData.columnNames.indexOf("ID");
        const titleColumnIndex = reportData.columnNames.indexOf("Title");
        const emailColumnIndex = reportData.columnNames.indexOf("User");
        const startDateColumnIndex = reportData.columnNames.indexOf("Start DateTime");
        const endDateColumnIndex = reportData.columnNames.indexOf("End DateTime");
        const currentUserEmail = IndexLibrary.GetUserEmail();

        const userLookup = await IndexLibrary.getUserLookupFor(
            emailColumnIndex !== -1 ? reportData.values.map(row => row[emailColumnIndex]) : []
        );

        for (const element of reportData.values) {
            let reportHtmlRow = '';
            const workItemId = idColumnIndex !== -1 ? element[idColumnIndex] : element[0];
            const workItemUrl = escapeHtml(
                `https://dev.azure.com/${await IndexLibrary.GetAccountNameAsync()}/${project}/_workitems/edit/${encodeURIComponent(workItemId)}/`
            );

            for (let i = 0; i < element.length; i++) {
                if (i === idColumnIndex) {
                    reportHtmlRow += `<td><a href="${workItemUrl}" target="_blank" style="text-decoration: underline; color:#0078d4;">${escapeHtml(element[i])}</a> </td>`;
                }
                else if (i === titleColumnIndex && titleColumnIndex !== -1) {
                    reportHtmlRow += `
                <td><a href="${workItemUrl}" target="_blank" style="text-decoration: underline; color:#0078d4;"> ${escapeHtml(element[i])}</a></td>`;
                }
                else if (i == emailColumnIndex) {
                    const user = userLookup[element[i]?.toLowerCase()];
                    const userName = (user ? user.name || element[i] : element[i]) || '';
                    const userEmail = (element[i] || '').toString();
                    const avatarLink = user ? user.avatar || "" : "";
                    const userNameTrimmed = userName.trim();
                    const userEmailTrimmed = userEmail.trim();
                    let tooltipText = "";
                    if (userNameTrimmed && userEmailTrimmed && userNameTrimmed.toLowerCase() !== userEmailTrimmed.toLowerCase()) {
                        tooltipText = `${userNameTrimmed}\n${userEmailTrimmed}`;
                    } else {
                        tooltipText = userNameTrimmed || userEmailTrimmed || "";
                    }

                    const safeDisplayName = escapeHtml(userNameTrimmed || userEmailTrimmed);
                    const safeEmail = escapeHtml(userEmailTrimmed || userNameTrimmed);
                    reportHtmlRow += "<td class='user' title='" + escapeHtml(tooltipText) + "'>";
                    if (avatarLink) {
                        reportHtmlRow += "<img src='" + escapeHtml(avatarLink) + "' class='avatar-img' alt='Avatar' /> ";
                    } else {
                        const emailTrimmed = userEmailTrimmed || '';
                        reportHtmlRow += "<span class='avatar'>" + escapeHtml(IndexLibrary.getInitials(emailTrimmed)) + "</span> ";
                    }
                    reportHtmlRow += "<span class='user-identity'><span class='user-name'>" + safeDisplayName + "</span><span class='user-email'>" + safeEmail + "</span></span></td>";
                }
                else if ((i === startDateColumnIndex || i === endDateColumnIndex) && element[i]) {
                    reportHtmlRow += `<td>${escapeHtml(IndexLibrary.convertUtcToLocal(element[i]))}</td>`;
                }
                else {
                    reportHtmlRow += `<td>${escapeHtml(element[i])}</td>`;
                }
            }
            const rowUserEmail = emailColumnIndex !== -1 ? element[emailColumnIndex] : null;
            const startIndex = reportData.columnNames.indexOf("Start Time");
            const endIndex = reportData.columnNames.indexOf("End Time");
            const descIndex = reportData.columnNames.indexOf("Description");
            const billableIndex = reportData.columnNames.indexOf("Is Billable");
            const startVal = startIndex !== -1 ? element[startIndex] : null;
            const endVal = endIndex !== -1 ? element[endIndex] : null;
            const descVal = descIndex !== -1 ? element[descIndex] : '';
            const billableVal = billableIndex !== -1 ? element[billableIndex] : false;
            const editLinkHtml = rowUserEmail === currentUserEmail && !isOrglicenseExpired
                ? `<a href="#"
                    class="editTimesheet"
                    data-timesheet-id="${escapeHtml(element[1])}"
                    data-workitem-id="${escapeHtml(workItemId)}"
                    data-workitem-title="${escapeHtml(element[titleColumnIndex] || '')}"
                    data-start="${escapeHtml(startVal || '')}"
                    data-end="${escapeHtml(endVal || '')}"
                    data-description="${escapeHtml(descVal)}"
                    data-billable="${escapeHtml(billableVal)}"
                    >
                    <i class="fa-regular fa-pen-to-square"></i>
                    </a>`
                : '';

            reportHtml += `<tr>
                ${reportHtmlRow}
                <td>${editLinkHtml}</td>
            </tr>`;
        }

        reportHtml += "</tbody></table>";
        $("#reportContainer").html(reportHtml);
        RenderReportPaging();
        $(".editTimesheet").on('click', async function () {
            const timesheetId = $(this).data('timesheet-id');
            const workItemId = $(this).data('workitem-id');
            const workItemTitle = $(this).data('workitem-title');

            const startRaw = $(this).data('start');
            const endRaw = $(this).data('end');
            const start = startRaw ? new Date(startRaw) : null;
            const end = endRaw ? new Date(endRaw) : null;

            const description = $(this).data('description') || '';
            const isBillable = $(this).data('billable') || false;

            IndexLibrary.HandleEditLoggedTimeClick({
                EditWorkItem: true,
                timesheetId,
                workItemId,
                workItemTitle,
                workStarted: start ? start.toISOString() : null,
                workEnded: end ? end.toISOString() : null,
                description,
                isBillable,
                organizationName: await IndexLibrary.GetAccountNameAsync(),
                timesheetTable: $("#timesheetsTable"),
                totalLoggedHoursLabel: $("#workitem-page-logged-hours-button"),
                apiUrl: baseAPIUrl,
                azureAuthenticationHeader: azureAuthenticationHeader
            });
        });

    } catch (error) {
        console.error(error);
        $("#reportContainer").html(`<span><i>Error generating report: ${escapeHtml(error.message)}</i></span>`);
        $("#reportPagingContainer").empty();
    } finally {
        $("#loadingSpinner").hide();
        $("#reportContainer").show();
    }

}

async function SetDefaultDateRangeFilter() {
    var d = new Date();
    let day = d.getDay();
    while (day !== 0) {
        d.setDate(d.getDate() - 1);
        day = d.getDay();
    }
    $("#reportFromDate").val(d.toLocaleDateString('en-US'));
    while (day !== 6) {
        d.setDate(d.getDate() + 1);
        day = d.getDay();
    }
    $("#reportToDate").val(d.toLocaleDateString('en-US'));
}
async function SetupPermissions() {

    licensedUserType = await IndexLibrary.GetUserLicensesType(fieldName, true);

    if (isOrglicenseExpired) {
        setButtonState("#btnExport", false);
        setButtonState("#btnReportingTemplates", false);
    } else {
        setButtonState("#btnReportingTemplates", true);
        setButtonState("#ddlTemplates", true);
        $("#btnReportingTemplates_Wrapper").removeAttr('title');
        $("#ddlTemplates").removeAttr('title');
        $("#btnReportingTemplates").on('click', function () {
            OpenAdvancedReportingPanel();
        });
    }
}

async function LoadWorkTypes() {
    try {
        const allWorkTypes = await IndexLibrary.GetWorkTypes(baseAPIUrl);
        let workTypeFilterHtml = "";

        allWorkTypes.forEach(element => {
            const checkboxId = `chkWorkTypeFilter_${element.id}`;
            workTypeFilterHtml += `
                <div class="form-check">
                    <input class="form-check-input chkWorkTypeFilter" type="checkbox" id="${checkboxId}" data-work-type="${element.id}">
                    <label class="form-check-label" for="${checkboxId}" style="font-size:14px; padding-left:5px">
                        ${element.trackingWorkTypeTitle}
                    </label>
                </div>
            `;
        });

        $("#ddlWorkTypeFilter").html(workTypeFilterHtml);

        $(".chkWorkTypeFilter").on('change', function () {
            const workType = $(this).data("workType");
            const isChecked = $(this).is(":checked");

            if (isChecked && !workTypeFilter.includes(workType)) {
                workTypeFilter.push(workType);
            } else if (!isChecked) {
                const index = workTypeFilter.indexOf(workType);
                if (index > -1) workTypeFilter.splice(index, 1);
            }
        });

    } catch (error) {
        console.error("Failed to load work types:", error);
    }
}


function SelectUserFromSuggestion(item) {
    $("#txtUserFilter").val($(item).data('displayName') + " (" + $(item).data('email') + ")");
    $("#txtUserFilter").data('email', $(item).data('email'));
    $("#userSuggestions").hide();
}

function RenderReportPaging() {
    $("#reportPagingContainer").empty();
    if (reportTotalPages <= 1) return;

    var pagingHtml = `<button onclick="GotoReportPage(${currentReportPage - 1})" ${currentReportPage <= 1 ? "disabled" : ""} class="pagination-button"> &lt; </button>`;

    const windowSize = 5;
    let start = Math.max(1, currentReportPage - Math.floor(windowSize / 2));
    let end = Math.min(reportTotalPages, start + windowSize - 1);
    start = Math.max(1, end - windowSize + 1);

    if (start > 1) {
        pagingHtml += `<button onclick="GotoReportPage(1)" class="pagination-button" style="${1 === currentReportPage ? "background:#0078d4;color:white;" : ""}">1</button>`;
        if (start > 2) pagingHtml += `<span class="pagination-ellipsis" style="padding:0 6px">&hellip;</span>`;
    }
    for (let i = start; i <= end; i++) {
        pagingHtml += `<button onclick="GotoReportPage(${i})" class="pagination-button" style="${i === currentReportPage ? "background:#0078d4;color:white;" : ""}">${i}</button>`;
    }
    if (end < reportTotalPages) {
        if (end < reportTotalPages - 1) pagingHtml += `<span class="pagination-ellipsis" style="padding:0 6px">&hellip;</span>`;
        pagingHtml += `<button onclick="GotoReportPage(${reportTotalPages})" class="pagination-button" style="${reportTotalPages === currentReportPage ? "background:#0078d4;color:white;" : ""}">${reportTotalPages}</button>`;
    }

    pagingHtml += `<button onclick="GotoReportPage(${currentReportPage + 1})" ${currentReportPage >= reportTotalPages ? "disabled" : ""} class="pagination-button"> &gt; </button>`;

    $("#reportPagingContainer").html(`<div id="reportPaging" style="position: fixed; width: 100%; bottom: 0; background: var(--da-surface); padding-top: 5px; padding-bottom: 15px; text-align: left;">${pagingHtml}</div>`);
}

async function GotoReportPage(page) {
    if (page < 1 || page > reportTotalPages || page === currentReportPage) return;
    await GenerateTimesheetReport(page);
}

async function ExportTimesheetReport() {
    const accountName = await IndexLibrary.GetAccountNameAsync();
    const accountId = await IndexLibrary.GetAccountIdAsync();
    const userEmail = (licensedUserType === 0 || licensedUserType === "")
        ? IndexLibrary.GetUserEmail()
        : $("#txtUserFilter").data('email');

    setButtonState("#btnExport", false);
    $("#loadingSpinner").show();
    try {
        const project = await IndexLibrary.GetCurrentProjectName();
        const startDate = $("#reportFromDate").val();
        const endDate = $("#reportToDate").val();

        const allUsers = await IndexLibrary.getAllUsers();
        const userLookup = IndexLibrary.buildUserLookup(allUsers);
        const userDisplayNames = {};
        Object.keys(userLookup).forEach(email => {
            if (userLookup[email] && userLookup[email].name) userDisplayNames[email] = userLookup[email].name;
        });

        const response = await IndexLibrary.PostRequest({
            endpoint: '/api/Timesheet/ExportReport',
            body: {
                userEmail: userEmail,
                billingType: billingTypeFilter,
                workType: workTypeFilter,
                dateFrom: IndexLibrary.convertLocalToUtc(startDate),
                dateTo: IndexLibrary.convertLocalToUtc(endDate),
                organizationName: accountName,
                project: project,
                licensedUserType: licensedUserType,
                generatedBy: IndexLibrary.GetUserEmail(),
                templateId: parseInt($("#ddlTemplates").val()) || 0,
                userDisplayNames: userDisplayNames
            }
        });

        if (!response.ok) throw new Error("Failed to export report.");

        const blob = await response.blob();
        const link = document.createElement("a");
        link.href = URL.createObjectURL(blob);
        link.download = "PerfectTimesheetsReport.csv";
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        URL.revokeObjectURL(link.href);
    } catch (error) {
        console.error(error);
        Swal.fire({ icon: 'error', title: 'Export failed', text: error.message });
    } finally {
        $("#loadingSpinner").hide();
        setButtonState("#btnExport", !isOrglicenseExpired);
    }
}


function OpenAdvancedReportingPanel() {
    IndexLibrary.HandleAdvancedReportingCreationClick({ apiUrl: baseAPIUrl });
}

async function PopulateTemplatesDropdown() {
    try {
        const templates = await IndexLibrary.GetAllReportingTemplates(azureAuthenticationHeader);
        const dropdown = document.getElementById('ddlTemplates');

        // Clear existing options
        dropdown.innerHTML = '';

        // Optionally, add a default placeholder
        const defaultOption = document.createElement('option');
        defaultOption.value = '0';
        defaultOption.textContent = 'Default Report Template';
        dropdown.appendChild(defaultOption);

        if (!licensedUserType == '0') {
            // Populate with templates
            templates.forEach(template => {
                const option = document.createElement('option');
                option.value = template.id;
                option.textContent = template.templateName;
                dropdown.appendChild(option);
            });
        }
    } catch (error) {
        console.error('Error populating templates dropdown:', error);
    }
}


function sortTable(columnIndex) {
    const table = document.getElementById("reportTable");
    const tbody = table.tBodies[0];
    const rows = Array.from(tbody.rows);

    if (currentSortColumn === columnIndex) {
        currentSortOrder = currentSortOrder === 'asc' ? 'desc' : 'asc';
    } else {
        currentSortOrder = 'asc';
        currentSortColumn = columnIndex;
    }

    // Detect data type
    const firstValue = rows[0]?.cells[columnIndex]?.innerText.trim();
    const dataType = detectDataType(firstValue);

    // Sort rows based on detected type
    rows.sort((a, b) => {
        let valA = a.cells[columnIndex].innerText.trim();
        let valB = b.cells[columnIndex].innerText.trim();

        let aVal, bVal;

        switch (dataType) {
            case 'number':
                aVal = parseFloat(valA);
                bVal = parseFloat(valB);
                break;
            case 'date':
                aVal = new Date(valA);
                bVal = new Date(valB);
                break;
            default:
                aVal = valA.toLowerCase();
                bVal = valB.toLowerCase();
        }

        if (aVal < bVal) return currentSortOrder === 'asc' ? -1 : 1;
        if (aVal > bVal) return currentSortOrder === 'asc' ? 1 : -1;
        return 0;
    });

    tbody.innerHTML = '';
    rows.forEach(row => tbody.appendChild(row));
    updateHeaderArrows(table, columnIndex, currentSortOrder);
}

function detectDataType(value) {
    if (!value) return 'text';

    // Check if it's a valid date
    const date = new Date(value);
    if (!isNaN(date.getTime())) return 'date';

    // Check if it's a number
    if (!isNaN(parseFloat(value)) && isFinite(value)) return 'number';

    return 'text';
}

function updateHeaderArrows(table, columnIndex, order) {
    const headers = table.querySelectorAll("th");

    headers.forEach((th, i) => {
        if (!th.dataset.originalText) {
            th.dataset.originalText = th.innerText.replace(/\s*[â–²â–¼]$/, '');
        }

        th.textContent = th.dataset.originalText;

        if (i === columnIndex) {
            th.insertAdjacentHTML('beforeend', order === 'asc' ? ' &#9650;' : ' &#9660;');
        }
    });
}
window.addEventListener('message', (event) => {
    if (localStorage.getItem("timeSheetChanged") === "true") {
        localStorage.removeItem("timeSheetChanged");
        GenerateTimesheetReport();
    }
});

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

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