(function () {

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

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

    function qaEscapeJsArg(value) {
        return qaEscapeHtml(JSON.stringify(String(value ?? "")));
    }

    let timeEntries = [];
    let loggedInUserEmail = "";
    let userLookup = {};
    let currentWorkItemId = 0;
    let timeloggingWorkItemId = 0;
    let isTimeLoggingStarted = false;
    let context = null;
    let tableBody = null;
    const PAGE_SIZE = 5;
    let currentPage = 1;
    let tooltipEl = null;
    let hideTimeout = null;
    let defaultWorkTypeId = null;
    let defaultWorkTypeTitle = "";
    let hasTimesheetLicense = true;
    const NO_LICENSE_TOOLTIP = "You don't have Timesheet License";

    async function init() {
        context = await getContext();
        tableBody = document.querySelector("#timeTable tbody");
        applyLogTimePermission();
        if (!tableBody) return;

        loggedInUserEmail = context.userEmail?.toLowerCase();
        currentWorkItemId = context.workItemId;

        bindUIEvents();
        GetTimeTrackingStatus();
        loadData();
        await resolveDefaultWorkTypeId();
        resolveQuickLogButtonMinutes();

        const allUsers = await IndexLibrary.getAllUsers();
        userLookup = IndexLibrary.buildUserLookup(allUsers);
        renderTable();
    }

    function formatQuickLogLabel(minutes) {
        const hours = Math.floor(minutes / 60);
        const mins = minutes % 60;
        if (hours === 0) return `${mins}m`;
        if (mins === 0) return `${hours}h`;
        return `${hours}h${mins}m`;
    }

    function renderQuickLogButtons(minutesList) {
        const row = document.querySelector(".timesheet-quicklog-row");
        if (!row) return;

        const workTypeLabel = defaultWorkTypeTitle || "default work type";
        row.innerHTML = minutesList.map(minutes => {
            const label = formatQuickLogLabel(minutes);
            const title = hasTimesheetLicense ? `Log ${label} of ${workTypeLabel} time` : NO_LICENSE_TOOLTIP;
            return `<button class="timesheet-action-btn" data-minutes="${minutes}" title="${title}">${label}</button>`;
        }).join("");

        attachQuickLogButtonListeners();
    }

    function attachQuickLogButtonListeners() {
        document.querySelectorAll(".timesheet-quicklog-row [data-minutes]").forEach(btn => {
            btn.addEventListener("click", () => {
                const minutes = parseInt(btn.dataset.minutes, 10);
                QuickLogTime(minutes, btn);
            });
        });
    }

    async function resolveQuickLogButtonMinutes() {
        try {
            const res = await IndexLibrary.GetRequest({
                baseAPIUrl: context.baseAPIUrl,
                endpoint: `/api/TimesheetSettings/GetSettings/${encodeURIComponent(context.organizationName)}`,
                azureAuthenticationHeader: context.accessToken,
                organizationName: context.organizationName,
                organizationId: context.organizationId
            });

            if (!res.ok) return;

            const json = await res.json();
            const minutes = Array.isArray(json.quickLogButtonMinutes)
                ? json.quickLogButtonMinutes.filter(n => Number.isInteger(n) && n > 0)
                : [];

            if (minutes.length === 4) {
                renderQuickLogButtons(minutes);
            }
        } catch {
            // Static default buttons already in the DOM will keep working.
        }
    }

    async function resolveDefaultWorkTypeId() {
        try {
            const res = await IndexLibrary.GetRequest({
                baseAPIUrl: context.baseAPIUrl,
                endpoint: `/api/TrackingWorkType/GetAll/${encodeURIComponent(context.organizationName)}`,
                azureAuthenticationHeader: context.accessToken,
                organizationName: context.organizationName,
                organizationId: context.organizationId
            });

            if (!res.ok) return;

            const types = await res.json();
            if (!Array.isArray(types)) return;

            const match = types.find(t => !t.isDeleted && t.isDefault);

            if (match) {
                defaultWorkTypeId = match.id;
                defaultWorkTypeTitle = match.trackingWorkTypeTitle || "";
            }
        } catch {
            // Quick-log will still work without a resolved work type id.
        }
    }


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

    function bindUIEvents() {
        document.getElementById("addTime")?.addEventListener("click", () => {
            if (!hasTimesheetLicense) return;

            if (typeof IndexLibrary?.HandleTimeTrackingMenuOptionClick === "function") {
                IndexLibrary.HandleTimeTrackingMenuOptionClick({
                    id: currentWorkItemId,
                    apiUrl: context.baseAPIUrl
                });
            }
        });

        document.getElementById("prev")?.addEventListener("click", () => {
            if (currentPage > 1) {
                currentPage--;
                renderTable();
            }
        });

        document.getElementById("next")?.addEventListener("click", () => {
            const totalPages = Math.ceil(timeEntries.length / PAGE_SIZE);
            if (currentPage < totalPages) {
                currentPage++;
                renderTable();
            }
        });

        attachQuickLogButtonListeners();
    }

    function QuickLogTime(minutes, btn) {
        if (!hasTimesheetLicense) return;

        const workStarted = new Date();
        const workEnded = new Date(workStarted.getTime() + minutes * 60000);
        const label = formatQuickLogLabel(minutes);

        if (btn) btn.disabled = true;

        IndexLibrary.PostRequest({
            baseAPIUrl: context.baseAPIUrl,
            endpoint: `/api/Timesheet/CreateTimesheet`,
            azureAuthenticationHeader: context.accessToken,
            organizationName: context.organizationName,
            organizationId: context.organizationId,
            headers: {
                DevOpsProjectId: String(context.projectId)
            },
            body: {
                organizationName: context.organizationName,
                workItemId: currentWorkItemId,
                userEmail: context.userEmail,
                workStarted: workStarted.toISOString(),
                workEnded: workEnded.toISOString(),
                trackingWorkItemTypeId: defaultWorkTypeId,
                description: "",
                isBillable: false,
                projectId: context.projectId,
                projectName: context.projectName
            }
        })
            .then(res => {
                if (res.ok) {
                    IndexLibrary.ShowToast("success", `Logged ${label} of ${defaultWorkTypeTitle || "default work type"} time`);
                    loadData();
                } else {
                    IndexLibrary.ShowToast("error", "Failed to log time. Please try again.");
                }
            })
            .catch(() => {
                IndexLibrary.ShowToast("error", "Failed to log time. Please try again.");
            })
            .finally(() => {
                if (btn) btn.disabled = false;
            });
    }

    function renderTimeLoggingButton() {
        const container = document.getElementById("timeLoggingContainer");
        if (!container || !currentWorkItemId) return;

        if (!isTimeLoggingStarted) {
            const title = hasTimesheetLicense ? "Start time tracking for this work item" : NO_LICENSE_TOOLTIP;
            container.innerHTML = `
                <button class="timesheet-action-btn" onclick="StartStopTimeLogging()" title="${qaEscapeHtml(title)}">
                    <i class="bi bi-play"></i>
                    Start
                </button>
            `;
            return;
        }

        const workItemUrl = `https://dev.azure.com/${context.organizationName}/_workitems/edit/${timeloggingWorkItemId}`;
        const stopTitle = hasTimesheetLicense ? "Stop time tracking for this work item" : NO_LICENSE_TOOLTIP;

        container.innerHTML = `
            <div style="display:flex; align-items:center; gap:8px;">
                <div class="workitem-pill" onclick="window.open(${qaEscapeJsArg(workItemUrl)}, '_blank')" title="Open the work item currently being tracked">
                    <i class="bi bi-clock"></i>
                    <span id="workItemId">${qaEscapeHtml(timeloggingWorkItemId)}</span>
                </div>
                <button class="timesheet-action-btn" onclick="StartStopTimeLogging()" title="${qaEscapeHtml(stopTitle)}">
                    <i class="bi bi-stop"></i>
                    Stop
                </button>
            </div>
        `;
    }

    window.StartStopTimeLogging = async function () {
        if (!hasTimesheetLicense) return;

        const endpoint = isTimeLoggingStarted
            ? `/api/Timesheet/StopTimeLogging`
            : `/api/Timesheet/StartTimeLogging`;

        IndexLibrary.PostRequest({
            baseAPIUrl: context.baseAPIUrl,
            endpoint,
            azureAuthenticationHeader: context.accessToken,
            organizationName: context.organizationName,
            organizationId: context.organizationId,
            headers: {
                DevOpsProjectId: String(context.projectId)
            },
            body: {
                organizationName: context.organizationName,
                workItemId: currentWorkItemId,
                userEmail: context.userEmail,
                projectId: context.projectId,
                projectName: context.projectName
            }
        })
            .then(r => r.json())
            .then(success => {
                if (success === true) {
                    isTimeLoggingStarted = !isTimeLoggingStarted;
                    timeloggingWorkItemId = currentWorkItemId;
                    renderTimeLoggingButton();
                    loadData();
                }
            });
    };




    function GetTimeTrackingStatus() {
        IndexLibrary.PostRequest({
            baseAPIUrl: context.baseAPIUrl,
            endpoint: `/api/Timesheet/IsTimeLoggingStarted`,
            azureAuthenticationHeader: context.accessToken,
            organizationName: context.organizationName,
            organizationId: context.organizationId,
            headers: {
                DevOpsProjectId: String(context.projectId)
            },
            body: {
                organizationName: context.organizationName,
                userEmail: context.userEmail
            }
        })
            .then(r => r.json())
            .then(json => {
                isTimeLoggingStarted = json.isStarted === true;
                timeloggingWorkItemId = json.workItemId || 0;
                renderTimeLoggingButton();
            });
    }

    async function loadData() {
        if (!currentWorkItemId) return;

        IndexLibrary.PostRequest({
            baseAPIUrl: context.baseAPIUrl,
            endpoint: `/api/Timesheet/GetTimesheetsByWorkItemId`,
            azureAuthenticationHeader: context.accessToken,
            organizationName: context.organizationName,
            organizationId: context.organizationId,
            headers: {
                DevOpsProjectId: String(context.projectId)
            },
            body: {
                organizationName: context.organizationName,
                workItemId: currentWorkItemId,
                userEmail: context.userEmail
            }
        })
            .then(res => res.json())
            .then(json => {
                timeEntries = json.map(item => ({
                    date: formatFullDateTime(item.workStarted),
                    hours: parseFloat(item.totalTimeSpent),
                    user: item.userEmail,
                    entryUserEmail: item.userEmail,
                    timesheetId: item.timesheetId,
                    isBillable: item.isBillable,
                    description: item.description || "",
                    workType: item.workType || "",
                    startTime: item.workStarted,
                    endTime: item.workEnded
                }));


                currentPage = 1;
                renderTable();
            })
            .catch(() => {
                timeEntries = [];
                renderTable();
            });
    }

    function renderTable() {
        tableBody.innerHTML = "";

        if (!timeEntries.length) {
            renderEmptyState();
            updateTotalHours();
            return;
        }

        const startIndex = (currentPage - 1) * PAGE_SIZE;
        const endIndex = Math.min(startIndex + PAGE_SIZE, timeEntries.length);
        const pageEntries = timeEntries.slice(startIndex, endIndex);

        IndexLibrary.loadAvatarsFor(pageEntries.map(entry => entry.user))
            .then(loaded => { if (loaded) renderTable(); });

        pageEntries.forEach(row => {
            const tr = document.createElement("tr");

            const entryUserEmail = row.user?.toLowerCase();
            const canEdit = loggedInUserEmail && entryUserEmail && loggedInUserEmail === entryUserEmail;

            const cellContent = document.createElement("td");
            const iconWrapper = document.createElement("div");
            iconWrapper.className = "action-icon-wrapper";

            if (canEdit) {
                const pencilSpan = document.createElement("span");
                pencilSpan.className = "action-icons pencil";
                pencilSpan.dataset.timesheetId = row.timesheetId;
                pencilSpan.title = "Edit";
                pencilSpan.innerHTML = `<i class="bi bi-pencil-square"></i>`;
                iconWrapper.appendChild(pencilSpan);
            }
            const infoSpan = document.createElement("span");
            infoSpan.className = "action-icons info";
            infoSpan.title = "Info";
            infoSpan.innerHTML = `<i class="bi bi-info-circle"></i>`;
            infoSpan.dataset.billable = row.isBillable;
            infoSpan.dataset.worktype = row.workType;
            infoSpan.dataset.description = row.description;
            infoSpan.dataset.starttime = row.startTime;
            infoSpan.dataset.endtime = row.endTime;
            infoSpan.addEventListener("mouseenter", showTooltip);
            infoSpan.addEventListener("mouseleave", scheduleHideTooltip);

            iconWrapper.appendChild(infoSpan);
            cellContent.appendChild(iconWrapper);

            const user = userLookup[row.user?.toLowerCase()];
            const userName = user ? user.name || row.user : row.user;
            const avatarLink = IndexLibrary.getCachedAvatar(row.user);

            let userHtml = "";

            if (avatarLink) {
                userHtml = `
                        <div class="user-cell">
                            <img src="${qaSafeUrl(avatarLink)}" class="avatar-img" />
                            <span>${qaEscapeHtml(userName)}</span>
                        </div>
                    `;
            } else {
                userHtml = `
                        <div class="user-cell">
                            <span class="avatar">${qaEscapeHtml(getInitials(row.user))}</span>
                            <span>${qaEscapeHtml(userName)}</span>
                        </div>
                    `;
            }

            tr.innerHTML = `
                    <td class="start-date-time">${qaEscapeHtml(row.date)}</td>
                    <td>${qaEscapeHtml(row.endTime ? IndexLibrary.formatHours(row.hours) : "Active")}</td>

                    <td>${userHtml}</td>
                `;
            tr.appendChild(cellContent);
            tableBody.appendChild(tr);
        });

        updateTotalHours();
        bindEditClicks();
        updatePaginationButtons();
        const paginationEl = document.querySelector(".pagination");
        if (paginationEl) {
            if (timeEntries.length === 0) {
                paginationEl.style.display = "none";
            } else {
                paginationEl.style.display = "flex";
            }
        }
    }
    function getInitials(email) {
        if (!email) return "";
        return email
            .split("@")[0]
            .split(".")
            .map(x => x[0])
            .join("")
            .toUpperCase();
    }


    function bindEditClicks() {
        document.querySelectorAll(".pencil").forEach(el => {
            el.addEventListener("click", function (e) {
                e.preventDefault();
                const timesheetId = this.dataset.timesheetId;
                if (typeof IndexLibrary?.HandleEditLoggedTimeClick === "function") {
                    IndexLibrary.HandleEditLoggedTimeClick({
                        workItemId: currentWorkItemId,
                        id: timesheetId,
                        timesheetTable: tableBody,
                        totalLoggedHoursLabel: document.getElementById("totalHours")
                    });
                }
            });
        });
    }


    function showTooltip(e) {
        const el = e.currentTarget;
        clearTimeout(hideTimeout);
        hideTooltip();

        tooltipEl = document.createElement("div");
        tooltipEl.className = "timesheet-tooltip";
        tooltipEl.innerHTML = `
        <div><strong>Timesheet Entry</strong></div>
        <div><strong>Start Time:</strong> ${qaEscapeHtml(formatFullDateTime(el.dataset.starttime))}</div>
        <div><strong>End Time:</strong> ${qaEscapeHtml(formatFullDateTime(el.dataset.endtime, "Active"))}</div>
        <div><strong>Billable:</strong> ${el.dataset.billable === "true" ? "Yes" : "No"}</div>
        <div><strong>Work Type:</strong> ${qaEscapeHtml(el.dataset.worktype || "-")}</div>
        <div><strong>Description:</strong> ${qaEscapeHtml(el.dataset.description || "-")}</div>
    `;

        tooltipEl.addEventListener("mouseenter", () => clearTimeout(hideTimeout));
        tooltipEl.addEventListener("mouseleave", hideTooltip);

        document.body.appendChild(tooltipEl);
        positionTooltip(el, tooltipEl);
    }



    function formatFullDateTime(dateString, fallback = "Running...") {
        if (!dateString) return fallback;
        const d = new Date(dateString);
        if (isNaN(d.getTime())) return fallback;
        return IndexLibrary.convertUtcToLocal(dateString);
    }

    function scheduleHideTooltip() {
        hideTimeout = setTimeout(hideTooltip, 150);
    }

    function hideTooltip() {
        if (tooltipEl) {
            tooltipEl.remove();
            tooltipEl = null;
        }
    }

    function positionTooltip(anchor, tooltip) {
        const rect = anchor.getBoundingClientRect();
        const tooltipRect = tooltip.getBoundingClientRect();
        let left = rect.left + window.scrollX + (rect.width / 2) - (tooltipRect.width / 2);
        let top = rect.top + window.scrollY + (rect.height / 2) - (tooltipRect.height / 2);

        if (left < 10) left = 10;

        if (left + tooltipRect.width > window.innerWidth + window.scrollX) {
            left = window.innerWidth + window.scrollX - tooltipRect.width - 10;
        }

        if (top < 10) top = 10;

        if (top + tooltipRect.height > window.innerHeight + window.scrollY) {
            top = window.innerHeight + window.scrollY - tooltipRect.height - 10;
        }

        tooltip.style.top = `${top}px`;
        tooltip.style.left = `${left}px`;
    }


    function updateTotalHours() {
        const total = timeEntries.reduce((sum, e) => sum + Number(e.hours || 0), 0);

        const el = document.getElementById("totalHours");
        if (el) {
            el.textContent = IndexLibrary.formatHours(total);
        }
    }




    function renderEmptyState() {
        const tr = document.createElement("tr");
        tr.innerHTML = `
            <td colspan="4" style="text-align:center; padding:20px;">
                No time entries found
            </td>
        `;
        tableBody.appendChild(tr);
    }

    function updatePaginationButtons() {
        const prevBtn = document.getElementById("prev");
        const nextBtn = document.getElementById("next");
        const totalPages = Math.ceil(timeEntries.length / PAGE_SIZE);

        if (prevBtn) prevBtn.disabled = currentPage <= 1;
        if (nextBtn) nextBtn.disabled = currentPage >= totalPages;
    }

    window.addEventListener('message', () => {
        if (localStorage.getItem("timeSheetChanged") === "true") {
            localStorage.removeItem("timeSheetChanged");
            loadData();
        }
    });
    function applyLogTimePermission() {
        const ptUserType = window.QALicenseContext.productUserTypes["timesheet"];

        if (ptUserType === null || ptUserType === undefined) {
            hasTimesheetLicense = false;

            const container = document.querySelector(".timesheet-left");
            if (container) {
                container.classList.add("license-disabled");
            }

            document.querySelectorAll(".timesheet-left button, .timesheet-quicklog-row button").forEach(btn => {
                btn.title = NO_LICENSE_TOOLTIP;
            });

            const quickLogRow = document.querySelector(".timesheet-quicklog-row");
            if (quickLogRow) {
                quickLogRow.classList.add("license-disabled");
            }
        }
    }

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

})();
